在 bash 中遍历数组不起作用
looping through array in bash does not work
我有一个数组 filesToDelete
并得到 echo $filesToDelete
的以下输出
value1 value2 value3 value4
当我尝试遍历数组以从当前文件夹中删除文件时:
for i in '${filesToDelete[@]}'
do
# rm $i
rm $i*.*;
done
内容如下:
rm: ”${filesToDelete[@]}*.*” can not be deleted: no such file or directroy
文件存在,我在正确的目录中可以执行删除方法,但仍然出现错误。
如果我改变循环:
for i in "${filesToDelete[@]}"
我收到包含 done
行的 Bad substitution
错误
因为我查找了google,建议在第一行使用#!/bin/bash
,我也是这样。
知道如何从数组中删除文件吗?
这里有一个简单的答案,但是用户出于某种原因删除了它,所以就在这里,简单而精彩:)
for file in $filesToDelete
do
rm "$file"*.*;
done
这比我的方法简单多了。感谢他,不管他是谁!
如果echo $filesToDelete
打印元素列表,则它不是数组;如果它是一个只打印第一个元素的实际数组。我很确定你实际拥有的只是一个用空格分隔元素的字符串。
您遇到的直接问题是您将变量 (/array) 引用放在单引号中,而 shell 不会在单引号内执行变量扩展。事实上,它不会对单引号的内容进行任何解析(除了查找闭引号)。在shell中,有3个主要的引用上下文:
- 在单引号内,根本不执行任何解释(变量引用、通配符等)。
- 在双引号内,变量引用(以及其他以
$
开头的内容)已完成,反引号命令和一些转义 (\
) 序列也是如此。一旦变量(等)被替换,就不会对替换值进行解析(这几乎总是你想要的)。
- 当不加引号时,变量引用(以及许多其他事情)完成,然后将替换值拆分为单词(由空格和其他空格分隔),并替换任何通配符。
由于 filesToDelete 显然是一个用空格分隔文件名的纯字符串,因此您需要引用它而不用引号将其拆分成单词。但是如果任何文件名包含空格 and/or 通配符,这可能会灾难性地失败。我的标准示例是 Apple 的 iTunes 2.0 安装程序,其中包含删除旧版本的命令;类似于 rm -R
。如果旧版本位于例如/Volumes/Data 2/Applications/iTunes.app,这会删除/Volumes/Data的全部内容,然后抱怨2/Applications/iTunes.app不存在。 Apple 很快就发布了 2.0.1 版,唯一的变化是在 </code> 的引用周围添加了双引号。 IIRC 他们还为一些客户购买了数据恢复软件。</p>
<p>如果您需要安全地存储多个文件名,请使用真正的数组。用 <code>filesToDelete=(value1 value2 value3 value4)
之类的东西创建它(请注意,此处也执行分词和通配符扩展,因此将所有变量引用用双引号引起来)。然后将它与类似的东西一起使用:
for i in "${filesToDelete[@]}"; do
rm "$i"*.*
done
请注意,在rm
命令中,我在变量引用两边加了双引号,但没有将需要解释为通配符的部分加起来。 (此外,在 shell 中,行尾不需要分号,因此我将其省略。)
我有一个数组 filesToDelete
并得到 echo $filesToDelete
value1 value2 value3 value4
当我尝试遍历数组以从当前文件夹中删除文件时:
for i in '${filesToDelete[@]}'
do
# rm $i
rm $i*.*;
done
内容如下:
rm: ”${filesToDelete[@]}*.*” can not be deleted: no such file or directroy
文件存在,我在正确的目录中可以执行删除方法,但仍然出现错误。
如果我改变循环:
for i in "${filesToDelete[@]}"
我收到包含 done
Bad substitution
错误
因为我查找了google,建议在第一行使用#!/bin/bash
,我也是这样。
知道如何从数组中删除文件吗?
这里有一个简单的答案,但是用户出于某种原因删除了它,所以就在这里,简单而精彩:)
for file in $filesToDelete
do
rm "$file"*.*;
done
这比我的方法简单多了。感谢他,不管他是谁!
如果echo $filesToDelete
打印元素列表,则它不是数组;如果它是一个只打印第一个元素的实际数组。我很确定你实际拥有的只是一个用空格分隔元素的字符串。
您遇到的直接问题是您将变量 (/array) 引用放在单引号中,而 shell 不会在单引号内执行变量扩展。事实上,它不会对单引号的内容进行任何解析(除了查找闭引号)。在shell中,有3个主要的引用上下文:
- 在单引号内,根本不执行任何解释(变量引用、通配符等)。
- 在双引号内,变量引用(以及其他以
$
开头的内容)已完成,反引号命令和一些转义 (\
) 序列也是如此。一旦变量(等)被替换,就不会对替换值进行解析(这几乎总是你想要的)。 - 当不加引号时,变量引用(以及许多其他事情)完成,然后将替换值拆分为单词(由空格和其他空格分隔),并替换任何通配符。
由于 filesToDelete 显然是一个用空格分隔文件名的纯字符串,因此您需要引用它而不用引号将其拆分成单词。但是如果任何文件名包含空格 and/or 通配符,这可能会灾难性地失败。我的标准示例是 Apple 的 iTunes 2.0 安装程序,其中包含删除旧版本的命令;类似于 rm -R
。如果旧版本位于例如/Volumes/Data 2/Applications/iTunes.app,这会删除/Volumes/Data的全部内容,然后抱怨2/Applications/iTunes.app不存在。 Apple 很快就发布了 2.0.1 版,唯一的变化是在 </code> 的引用周围添加了双引号。 IIRC 他们还为一些客户购买了数据恢复软件。</p>
<p>如果您需要安全地存储多个文件名,请使用真正的数组。用 <code>filesToDelete=(value1 value2 value3 value4)
之类的东西创建它(请注意,此处也执行分词和通配符扩展,因此将所有变量引用用双引号引起来)。然后将它与类似的东西一起使用:
for i in "${filesToDelete[@]}"; do
rm "$i"*.*
done
请注意,在rm
命令中,我在变量引用两边加了双引号,但没有将需要解释为通配符的部分加起来。 (此外,在 shell 中,行尾不需要分号,因此我将其省略。)