在bash中循环遍历数组不起作用

时间:2015-03-24 00:00:50

标签: arrays bash shell unix

我有一个数组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[@]}"

我收到包含Bad substitution

的行的done错误

当我查找谷歌时,建议在第一行使用#!/bin/bash,这对我来说也是一样。

知道如何从数组中删除文件吗?

2 个答案:

答案 0 :(得分:1)

如果echo $filesToDelete打印元素列表,则它不是数组;如果它是一个只打印第一个元素的实际数组。我很确定你实际拥有的只是一个用空格分隔元素的字符串。

您遇到的直接问题是您已将变量(/ array)引用放在单引号中,并且shell不会在单引号内执行变量扩展。实际上,它不会对单引号的内容进行任何解析(除了查找关闭引号)。在shell中,有3个主要的引用上下文:

  • 在单引号内,根本不会执行任何解释(变量引用,通配符等)。
  • 内部双引号,变量引用(以及以$开头的其他内容),以及反引号命令和一些转义(\)序列。一旦变量(etc)被替换,就不会对替换值进行解析(这几乎总是你想要的)。
  • 当不带引号时,变量引用(以及许多其他内容)完成,然后将替换值拆分为单词(由空格和其他空格分隔),并替换任何通配符。

由于filesToDelete显然是一个包含空格分隔文件名的普通字符串,因此您需要引用它而不将其分成单词。但是,如果任何文件名包含空格和/或通配符,这可能会导致灾难性的失败。我的标准示例是Apple的iTunes 2.0安装程序,其中包含删除旧版本的命令;像rm -R $1这样的东西。如果旧版本位于例如/ Volumes / Data 2 / Applications / iTunes.app,这将删除/ Volumes / Data 的全部内容,然后抱怨2 / Applications / iTunes.app不存在。 Apple之后很快发布了2.0.1版本,唯一的变化就是在$1的引用周围添加双引号。他们还为一些客户购买了数据恢复软件。

如果您需要安全地存储多个文件名,请使用真实数组。使用类似filesToDelete=(value1 value2 value3 value4)的内容创建它(请注意,此处也会执行单词拆分和通配符扩展,因此请将双引号中的任何变量引用包装起来)。然后使用类似的东西:

for i in "${filesToDelete[@]}"; do
    rm "$i"*.*
done

请注意,在rm命令中,我在变量引用周围放置了双引号,而不是需要将其解释为通配符的部分。 (另外,在shell中,在一行的末尾不需要分号,所以我把它留下了。)

答案 1 :(得分:0)

这里有一个简单的答案,但是用户出于某种原因将其删除了,所以这里简单明了:)

for file in $filesToDelete 
    do
    rm "$file"*.*;
done

这比我的apprach简单得多。谢谢他,无论他是谁!