如何使用for-each循环迭代bash中的文件路径?

时间:2013-02-25 10:38:23

标签: linux bash shell

以下命令尝试枚举当前目录中的所有*.txt个文件并逐个处理:

for line in "find . -iname '*.txt'"; do 
     echo $line
     ls -l $line; 
done

为什么会出现以下错误?:

ls: invalid option -- 'e'
Try `ls --help' for more information.

4 个答案:

答案 0 :(得分:117)

这是循环文件的更好方法,因为它处理文件名中的空格和换行符:

find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do
    echo "$line"
    ls -l "$line"    
done

答案 1 :(得分:18)

for - 循环将迭代所提供字符串上的每个(空格分隔)条目。

您实际上并不执行find命令,而是将其作为字符串(由for - 循环迭代)提供。 而不是双引号使用反引号或$()

for line in $(find . -iname '*.txt'); do 
     echo "$line"
     ls -l "$line"
done

此外,如果您的文件路径/名称包含空格,则此方法失败(因为for - 循环遍历空格分隔的条目)。相反,最好使用dogbanes answer中描述的方法。


澄清您的错误:

如上所述,for line in "find . -iname '*.txt'";遍历所有空格分隔的条目,即:

  • 找到
  • -iname
  • '* .txt'(我认为......)

前两个不会导致错误(除了不良行为),但第三个在执行时会出现问题:

ls -l -iname

许多(bash)命令可以组合单个字符选项,因此-iname-i -n -a -m -e相同。瞧:你的invalid option -- 'e'错误!

答案 2 :(得分:18)

使用文件名中的空格和换行符的更紧凑版本:

find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;

答案 3 :(得分:3)

使用command substitution而不是引号来执行find而不是将命令作为字符串传递:

for line in $(find . -iname '*.txt'); do 
     echo $line
     ls -l $line; 
done