Bash:通过管道将“查找”输出到“ readarray”


14

我正在尝试使用来搜索文件find,并将这些文件放入Bash数组中,以便可以对它们执行其他操作(例如lsgrep它们)。但是我不知道为什么readarray在将find输出通过管道传输时不读取输出。

假设我在当前目录中有两个文件,file1.txt并且file2.txt。因此find输出如下:

$ find . -name "file*"
./file1.txt
./file2.txt

因此,我想将其传送到一个数组,该数组的两个元素是字符串"./file1.txt""./file2.txt"(显然没有引号)。

我已经尝试过了,其中包括:

$ declare -a FILES
$ find . -name "file*" | readarray FILES
$ echo "${FILES[@]}"; echo "${#FILES[@]}"

0

echo输出中可以看到,我的数组为空。

那我到底在做什么错?为什么readarray不将find的输出作为标准输入读取并将这些字符串放入数组?

Answers:


21

使用管道时,bash在子shell中运行命令。因此,该数组已填充,但位于子外壳中,因此父外壳无法访问它。

使用流程替代:

readarray FILES < <(find)

请注意,它不适用于名称中包含换行符的文件。如果是这种情况,则需要更详细的语法:

readarray -d '' < <(find -print0)

3
为了支持换行,这就足够了:readarray -d '' < <(find your_args -print0)
VasyaNovikov

6

正确的解决方案是:

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)

这类似于Greg的BashFAQ 020详细解释的内容,并且此答案涵盖了

奇数命名文件(名称中不包含NUL),空格或换行都没有问题。并将结果设置在数组中,这对于进一步处理很有用。


太好了,这是我一开始要解决的问题的更好的解决方案。我的代表达到15时就+1 :)
villapx

3

readarray 也可以从标准输入中读取

readarray FILES <<< "$(find . -name "file*")"; echo "${#FILES[@]}"

这不适find -print0用于防止“意外”文件名。
roaima
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.