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

0x9*_*x90 51 linux bash shell

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

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

为什么我会收到以下错误?:

ls: invalid option -- 'e'
Try `ls --help' for more information.
Run Code Online (Sandbox Code Playgroud)

dog*_*ane 120

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

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

  • +1这不仅仅是更好,它是正确的. (10认同)
  • 适用于bash,而不是sh. (9认同)

Veg*_*ger 19

该for-loop将遍历所提供的串中的每个(空格分隔)条目.

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

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

此外,如果您的文件路径/名称包含空格,则此方法失败(因为for-loop迭代空格分隔的条目).相反,最好使用dogbanes回答中描述的方法.


澄清你的错误:

如上所述,for line in "find . -iname '*.txt'"; 迭代所有空格分隔的条目,这些条目是:

  • 找
  • .
  • -我的名字
  • '*.txt'(我想......)

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

ls -l -iname
Run Code Online (Sandbox Code Playgroud)

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

  • 如果名称中有空格,它将显示为for循环迭代的列表中的两个单独条目. (11认同)

jse*_*ras 18

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

find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;
Run Code Online (Sandbox Code Playgroud)

  • 这个答案要简单得多,它适用于Bash和更简单的sh(Ash)shell. (2认同)