我正在尝试使用一个数组来存储使用find
命令获取的文件名列表。
但是,在学校使用的bash中,该数组无法工作,尽管在我的笔记本电脑上可以工作。
所以我想知道是否有另一种方法可以实现这个目的,这是我目前拥有的:
array = (`find . -name "*.txt"`) #this will store all the .txt files into the array
那么我可以访问数组项并使用cat命令复制所有文件。
有没有不使用数组的方法?
我正在尝试使用一个数组来存储使用find
命令获取的文件名列表。
但是,在学校使用的bash中,该数组无法工作,尽管在我的笔记本电脑上可以工作。
所以我想知道是否有另一种方法可以实现这个目的,这是我目前拥有的:
array = (`find . -name "*.txt"`) #this will store all the .txt files into the array
那么我可以访问数组项并使用cat命令复制所有文件。
有没有不使用数组的方法?
您可以使用类似于以下代码:
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.Shawleya b.txt
。 - user unknowna=1; seq 3 | while read line; do a=2; done; echo $a
输出的是 1
。 - rvernicawhile
在管道中是第二个命令,因此在循环中所做的更改在循环结束后不会保留。我尝试将结果附加到循环外声明的变量时遇到了麻烦。引自这里:https://dev59.com/12Eh5IYBdhLWcg3wMA_M - Illya Moskvin我在使用Johannes Weiß的解决方案时遇到了问题,如果我只是执行echo命令,它可以对完整的文件列表进行操作。然而,如果我试图在下一行运行ffmpeg,脚本只会处理它遇到的第一个文件。我认为这可能与管道中的IFS有关,但我无法解决它,于是我改用for循环:
for i in $(find . -name '*.mov' );
do
echo "$i"
done
我认为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
不要在等号周围放置空格:
ar=($(find . -name "*.txt"))
尽可能避免使用反引号,因为它们已经过时了。它们很容易与撇号混淆,特别是在低质量的字体中,而且嵌套也不太好。
在大多数情况下,如果您直接通过-exec、-execdir、-ok或-okdir迭代查找结果,则效果最佳。
对于文件名中含有空格、换行符和制表符的情况,使用for和while循环难以正确处理。
find ./ -name "*.txt" -exec grep {} ";"
{} 不需要屏蔽。你经常会看到一个结合了find/xargs的组合,这样会启动额外的进程:
find ./ -name "*.txt" | xargs grep {} ";"
find . -name '*.txt' | while IFS= read -r FILE; do
echo "Copying $FILE.."
cp "$FILE" /destination
done
测试过带有空格的通用版本
echo $BASH_VERSION
4.2.46(2)-release
mkdir "spaces test"
cd spaces\ test/
touch 'test one'{1..5}
touch 'testone'{1..5}
mkdir test\ two
cd test\ two/
touch 'test one'{1..5}
创建并运行脚本
set -u
while read -r line
do
echo "$line"
done < <(find "spaces test" -type f)
在使用子shell的while循环中,有一种更改某些变量的另一种变体
concat=""
while read someVariable
do
echo "someVariable: '$someVariable'"
concat="$concat someVariable")
done < <(find "/Users/alex" -name "*.txt")
echo "concat: '$concat'"