如何处理bash脚本中的find结果?


71

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

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

所以我想知道是否还有另一种方法,这就是我所拥有的:

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

然后,我可以使用cat命令访问数组项并制作所有文件的副本。

还有另一种不用数组的方法吗?


如果您仅对文件感兴趣,则应将find结果限制为-type f。具有以.txt结尾的目录是有效的,例如。dir.txt
Uphill_ What'1

Answers:


130

您可以使用类似这样的方法:

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 2010年

D.Shawley,能否请您发布带有for循环的示例?我认为,它也应适用于名称中带有空格的文件。
Johannes Weiss 2010年

2
find与“ for”或“ while”一起使用通常是一个坏主意。您将文件名作为字符串传递,并获得了所有有关空格和掩码的问题,而将未掩码的{}与查找-exec,-execdir,-ok和-okdir一起使用是没有问题的。尝试a b.txt
用户未知

2
如果您希望循环产生副作用,那么在使用construct时我会非常小心。例如a=1; seq 3 | while read line; do a=2; done; echo $a版画1
rvernica

1
请注意:这while是在子shell中运行的,因为它是管道中的第二个命令,因此在循环退出后,在该循环中所做的更改将不可用。我很难将其附加到循环外声明的变量中。从这里:stackoverflow.com/questions/22691436/...
Illya Moskvin

25

我对约翰内斯·魏斯(JohannesWeiß)的解决方案有疑问,如果我只是做一个回声,它将适用于完整的文件列表。但是,如果我尝试在下一行运行ffmpeg,脚本将仅处理遇到的第一个文件。由于管道原因,我假设一些IFS有趣,但我无法弄清楚,而是使用for循环运行:

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

9
对于文件名中的空格,此操作失败
Spinup

12

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

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

您可以取消设置IFS以便重置IFS的行为以及为什么$需要使用IFS IFS=$'\n',请参见/unix/184863/what-is-the-意义-of-ifs-n-in- bash脚本


8

只是不要在等号旁加上空格:

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

如果可能,请避免使用反引号,因为反引号已被弃用。它们很容易与撇号混淆,尤其是在字体较差的情况下,而且嵌套效果也不佳。

在大多数情况下,如果直接使用-exec,-execdir,-ok或-okdir遍历查找结果,则将为您提供最佳服务。

对于文件名或换行符和制表符中的空白,难于正确执行for和while循环。

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

{}不需要屏蔽。您会经常看到find / xargs组合,它也会启动一个附加过程:

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

3
find . -name '*.txt' | while IFS= read -r FILE; do
    echo "Copying $FILE.."
    cp "$FILE" /destination
done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.