【问题标题】:How to perform a for-each loop over all the files under a specified path?如何对指定路径下的所有文件执行 for-each 循环?
【发布时间】:2020-11-30 19:07:17
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: linux bash shell


    【解决方案1】:

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

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

    【讨论】:

    • 当从 cronjob @reboot 中调用包含此 sn-p 的脚本时,我无法使其正常工作。它抱怨读取命令的 -d 标志,然后无法执行。否则效果很好。
    • 适用于 bash,而不适用于 sh。
    • @jww 在 macOS Sierra 上为我工作,GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
    【解决方案2】:

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

    您实际上并没有执行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'"; 遍历所有空格分隔的条目,它们是:

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

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

    ls -l -iname
    

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

    【讨论】:

    • 如果名称中有空格,它将在 for 循环迭代的列表中显示为两个单独的条目。
    【解决方案3】:

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

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

    【讨论】:

    • 这个答案要简单得多,它适用于 Bash 和更简单的 sh (Ash) shell。
    • 这个答案现在严重错误;恶意文件名可以运行任意代码。考虑一下如果有人创建了$(rm -rf ~).txt"; rm -rf ~; echo ".txt(双引号作为文件名的文字部分)会发生什么。
    • 写这个的安全(和更有效)的方法是find . -iname '*.txt' -exec sh -c 'for arg in "$@"; do echo "$arg"; ls -l "$arg"; done' _ {} +
    【解决方案4】:

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

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

    【讨论】:

    猜你喜欢
    • 2018-08-22
    • 2023-01-17
    • 2015-11-12
    • 1970-01-01
    • 1970-01-01
    • 2014-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多