54

以下命令尝试枚举*.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

4 回答 4

125

这是在处理文件名中的空格和换行符时循环文件的更好方法:

#!/bin/bash

find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do
    echo "$line"
    ls -l "$line"    
done
于 2013-02-25T11:39:12.453 回答
19

-loop将for遍历提供的字符串上的每个(空格分隔)条目。

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

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

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


为了澄清您的错误:

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

  • 寻找
  • .
  • -我的名字
  • '*.txt'(我认为...)

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

ls -l -iname

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

于 2013-02-25T10:43:44.277 回答
18

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

find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;
于 2013-02-26T10:54:31.833 回答
2

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

for line in $(find . -iname '*.txt'); do 
     echo $line
     ls -l $line; 
done
于 2013-02-25T10:42:25.350 回答