我正在尝试使用 搜索文件find
,并将这些文件放入 Bash 数组中,以便我可以对它们进行其他操作(例如ls
或grep
它们)。但我不明白为什么readarray
不读取通过find
管道输入的输出。
假设我在当前目录中有两个文件,file1.txt
并且file2.txt
. 所以find
输出如下:
$ find . -name "file*"
./file1.txt
./file2.txt
Run Code Online (Sandbox Code Playgroud)
所以我想把它传送到一个数组中,它的两个元素是字符串"./file1.txt"
和"./file2.txt"
(显然没有引号)。
我已经尝试过这个,除此之外还有其他一些事情:
$ declare -a FILES
$ find . -name "file*" | readarray FILES
$ echo "${FILES[@]}"; echo "${#FILES[@]}"
0
Run Code Online (Sandbox Code Playgroud)
从echo
输出中可以看出,我的数组是空的。
那么我到底做错了什么?为什么readarray
不将 readingfind
的输出作为其标准输入并将这些字符串放入数组中?
cho*_*oba 26
使用管道时,bash 在子 shell 中运行命令¹。因此,该数组已填充,但位于子 shell 中,因此父 shell 无法访问它。您可能还需要该-t
选项,以便不将该行分隔符存储在数组成员中,因为它们不是文件名的一部分。
使用进程替换:
readarray -t FILES < <(find .)
Run Code Online (Sandbox Code Playgroud)
请注意,它不适用于路径中带有换行符的文件。除非您可以保证不会出现这种情况,否则您希望使用 NUL 分隔的记录而不是换行分隔的记录:
readarray -td '' < <(find . -print0)
Run Code Online (Sandbox Code Playgroud)
(该-d
选项是在 bash 4.4 中添加的)
¹ 使用lastpipe
选项时的最后一个管道组件除外,但这仅适用于bash
.
小智 7
正确的解决办法是:
unset a; declare -a a
while IFS= read -r -u3 -d $'\0' file; do
a+=( "$file" ) # or however you want to process each file
done 3< <(find /tmp -type f -print0)
Run Code Online (Sandbox Code Playgroud)
这类似于Greg 的 BashFAQ 020详细解释的内容,该答案涵盖了.
对带有空格或换行符的奇怪命名文件(名称中不包含 NUL)没有问题。结果被设置在一个数组中,这使得它对进一步处理很有用。