【问题标题】:How can I process the results of find in a bash script?如何在 bash 脚本中处理 find 的结果?
【发布时间】:2023-03-17 21:40:01
【问题描述】:

我正在尝试使用find 命令使用数组来存储文件名列表。

由于某种原因,该阵列无法在学校使用的 bash 中运行,但我的程序可以在我自己的笔记本电脑上运行。

所以我想知道是否还有其他方法可以做到这一点,这就是我所拥有的:

array = (`find . -name "*.txt"`)  #this will store all the .txt files into the array

然后我可以使用 cat 命令访问数组项并复制所有文件。

还有其他不使用数组的方法吗?

【问题讨论】:

  • 如果您只对文件感兴趣,那么您应该使用-type f 限制查找结果。有一个以 .txt 结尾的目录是有效的,例如。目录.txt

标签: bash find


【解决方案1】:

你可以这样使用:

find . -name '*.txt' | while read line; do
    echo "Processing file '$line'"
done

例如,制作副本:

find . -name '*.txt' | while read line; do
    echo "Copying '$line' to /tmp"
    cp -- "$line" /tmp
done

【讨论】:

  • 在这里使用for 循环绝对是更好的选择。使用数组会起作用,只是它将整个列表读入一个变量,然后遍历该变量。此版本读取来自find 的每个文件名并内联处理它。
  • D.Shawley,您能否发布一个带有 for 循环的示例?我认为它也应该适用于名称中带有空格的文件。
  • find 与 'for' 或 'while' 一起使用通常是个坏主意。您将文件名作为字符串传递并得到所有与空格和掩码有关的问题,而将未掩码的 {} 与 finds -exec、-execdir、-ok、-okdir 一起使用是没有问题的。试试a b.txt
  • 如果你想循环产生副作用,我会非常小心地使用构造。例如a=1; seq 3 | while read line; do a=2; done; echo $a 打印1
  • 小心:这个while 在子shell 中运行,因为它是管道中的第二个命令,因此在循环退出后,在该循环中所做的更改不可用。我很难将它附加到循环外声明的变量中。从这里:stackoverflow.com/questions/22691436/…
【解决方案2】:

我对 Johannes Weiß 的解决方案有疑问,如果我只是做一个回显,它将适用于完整的文件列表。但是,如果我尝试在下一行运行 ffmpeg,则脚本只会处理它遇到的第一个文件。由于管道,我假设了一些 IFS 有趣的事情,但我无法弄清楚并使用 for 循环运行:

for i in $(find . -name '*.mov' ); 
do
    echo "$i"
done

【讨论】:

  • 文件名中的空格会失败
【解决方案3】:

我认为 starpause 有最干净的解决方案,但是当路径中有空格时它会失败。这可以通过设置IFS 来解决。因此正确答案是:

IFS=$'\n'
for i in $(find . -name '*.mov' ); 
do
    echo "$i"
done
unset IFS

您取消设置 IFS 是为了重置 IFS 的行为以及为什么在 IFS=$'\n' 中需要 $,请参阅 https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting

【讨论】:

    【解决方案4】:

    只是不要在等号周围放置空格:

    ar=($(find . -name "*.txt"))
    

    尽可能避免使用反引号,因为它们已被弃用。它们很容易与撇号混淆,尤其是在较差的字体中,而且它们的嵌套不太好。

    在大多数情况下,如果您直接使用 -exec、-execdir、-ok 或 -okdir 遍历查找结果,您会得到最好的服务。

    当涉及到文件名或换行符和制表符中的空白时,很难正确执行 For 和 while 循环。

    find ./ -name "*.txt" -exec grep {} ";"
    

    {} 不需要屏蔽。 您经常会看到一个组合 find/xargs 也会启动一个额外的过程:

    find ./ -name "*.txt" | xargs grep {} ";"
    

    【讨论】:

      【解决方案5】:
      find . -name '*.txt' | while IFS= read -r FILE; do
          echo "Copying $FILE.."
          cp "$FILE" /destination
      done
      

      【讨论】:

        【解决方案6】:

        在使用子shell的while循环中更改某些变量的另一种变体

        concat=""
        
        while read someVariable
        do
            echo "someVariable: '$someVariable'"
            concat="$concat someVariable")
        done < <(find "/Users/alex" -name "*.txt")
        
        echo "concat: '$concat'"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-03-11
          • 2012-12-24
          • 1970-01-01
          • 2011-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多