如何在 bash 脚本中处理 find 的结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2087001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I process the results of find in a bash script?
提问by Shellscriptbeginner
I'm trying to use an array to store a list of file names using the find
command.
我正在尝试使用数组来存储使用find
命令的文件名列表。
For some reason the array fails to work in the bash used by the school, my program works on my own laptop though.
由于某种原因,该数组无法在学校使用的 bash 中运行,但我的程序可以在我自己的笔记本电脑上运行。
So I was wondering if there's another way to do it, this is what i have:
所以我想知道是否有另一种方法可以做到这一点,这就是我所拥有的:
array = (`find . -name "*.txt"`) #this will store all the .txt files into the array
Then I can access the array items and make a copies of all the files using the cat command.
然后我可以访问数组项并使用 cat 命令制作所有文件的副本。
Is there another way to do it without using an array?
有没有另一种方法可以在不使用数组的情况下做到这一点?
回答by Johannes Weiss
You could use something like that:
你可以使用类似的东西:
find . -name '*.txt' | while read line; do
echo "Processing file '$line'"
done
E.g. make a copy:
例如制作一个副本:
find . -name '*.txt' | while read line; do
echo "Copying '$line' to /tmp"
cp -- "$line" /tmp
done
HTH
HTH
回答by starpause
I was having issue with Johannes Wei?'s solution, if I was just doing an echo it would work for the full list of files. However, if I tried running ffmpeg on the next line the script would only process the first file it encountered. I assumed some IFS funny business due to the pipe but I couldn't figure it out and ran with a for loop instead:
我对 Johannes Wei? 的解决方案有疑问,如果我只是在做一个回声,它将适用于完整的文件列表。但是,如果我尝试在下一行运行 ffmpeg,脚本将只处理它遇到的第一个文件。由于管道,我假设了一些 IFS 有趣的事情,但我无法弄清楚并使用 for 循环运行:
for i in $(find . -name '*.mov' );
do
echo "$i"
done
回答by user unknown
Just don't put blanks around the equals sign:
只是不要在等号周围放置空格:
ar=($(find . -name "*.txt"))
Avoid backticks, if possible, since they're deprecated. They can be easily confused with apostroph, especially in poor fonts, and they don't nest so well.
如果可能,请避免反引号,因为它们已被弃用。它们很容易与撇号混淆,尤其是在糟糕的字体中,而且它们的嵌套不太好。
In most cases you will be best served if you iterate through a find-result directly with -exec, -execdir, -ok or -okdir.
在大多数情况下,如果您直接使用 -exec、-execdir、-ok 或 -okdir 遍历查找结果,您将获得最佳服务。
For and while loops are hard to do right when it comes to blanks in filenames or newlines and tabs.
当涉及文件名或换行符和制表符中的空格时,for 和 while 循环很难正确执行。
find ./ -name "*.txt" -exec grep {} ";"
The {} doesn't need masking. You will often see a combination find/xargs which starts an additional process too:
{} 不需要屏蔽。你经常会看到一个组合 find/xargs 也启动了一个额外的过程:
find ./ -name "*.txt" | xargs grep {} ";"
回答by beruic
I think starpause has the cleanest solution, however it fails when there is whitespaces in paths. This is fixed by setting IFS
. The correct answer is therefore:
我认为 starpause 有最干净的解决方案,但是当路径中有空格时它会失败。这是通过设置修复的IFS
。因此,正确答案是:
IFS=$'\n'
for i in $(find . -name '*.mov' );
do
echo "$i"
done
unset IFS
You unset IFS in order to reset behaviour for IFS and as to why the $
is needed in IFS=$'\n'
, see https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting
您取消设置 IFS 以重置 IFS 的行为以及为什么$
需要在 中IFS=$'\n'
,请参阅https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in- bash 脚本
回答by ghostdog74
find . -name '*.txt' | while IFS= read -r FILE; do
echo "Copying $FILE.."
cp "$FILE" /destination
done