捕获 find 的输出.-print0 到 bash 数组中 [英] Capturing output of find . -print0 into a bash array

查看:24
本文介绍了捕获 find 的输出.-print0 到 bash 数组中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 find .-print0 似乎是在 bash 中获取文件列表的唯一安全方法,因为文件名可能包含空格、换行符、引号等.

Using find . -print0 seems to be the only safe way of obtaining a list of files in bash due to the possibility of filenames containing spaces, newlines, quotation marks etc.

但是,我很难真正让 find 的输出在 bash 或其他命令行实用程序中有用.我设法利用输出的唯一方法是将其通过管道传输到 perl,并将 perl 的 IFS 更改为 null:

However, I'm having a hard time actually making find's output useful within bash or with other command line utilities. The only way I have managed to make use of the output is by piping it to perl, and changing perl's IFS to null:

find . -print0 | perl -e '$/=""; @files=<>; print $#files;'

此示例打印找到的文件数,避免文件名中的换行符破坏计数的危险,如下所示:

This example prints the number of files found, avoiding the danger of newlines in filenames corrupting the count, as would occur with:

find . | wc -l

由于大多数命令行程序不支持以 null 分隔的输入,我认为最好的办法是捕获 find 的输出.-print0 在 bash 数组中,就像我在上面的 perl 片段中所做的那样,然后继续执行任务,无论它可能是什么.

As most command line programs do not support null-delimited input, I figure the best thing would be to capture the output of find . -print0 in a bash array, like I have done in the perl snippet above, and then continue with the task, whatever it may be.

我该怎么做?

这不起作用:

find . -print0 | ( IFS=$'' ; array=( $( cat ) ) ; echo ${#array[@]} )

一个更普遍的问题可能是:如何在 bash 中使用文件列表做有用的事情?

A much more general question might be: How can I do useful things with lists of files in bash?

推荐答案

无耻地从 Greg 的 BashFAQ 中窃取:

unset a i
while IFS= read -r -d $'' file; do
    a[i++]="$file"        # or however you want to process each file
done < <(find /tmp -type f -print0)

请注意,此处使用的重定向构造 (cmd1 < <(cmd2)) 与更常用的管道 (cmd2 | cmd1) -- 如果命令是 shell 内置命令(例如 while),则管道版本在子 shell 中执行它们,并且它们设置的任何变量(例如数组 a)都是当他们退出时丢失.<代码>cmd1 <<(cmd2) 仅在子 shell 中运行 cmd2,因此该数组在其构造之后仍然存在.警告:这种形式的重定向只在 bash 中可用,甚至在 sh-emulation 模式下的 bash 也不可用;你必须以 #!/bin/bash 开始你的脚本.

Note that the redirection construct used here (cmd1 < <(cmd2)) is similar to, but not quite the same as the more usual pipeline (cmd2 | cmd1) -- if the commands are shell builtins (e.g. while), the pipeline version executes them in subshells, and any variables they set (e.g. the array a) are lost when they exit. cmd1 < <(cmd2) only runs cmd2 in a subshell, so the array lives past its construction. Warning: this form of redirection is only available in bash, not even bash in sh-emulation mode; you must start your script with #!/bin/bash.

另外,因为文件处理步骤(在这种情况下,只是 a[i++]="$file",但您可能想直接在循环中做一些更有趣的事情)将其输入重定向,它不能使用任何可能从标准输入读取的命令.为了避免这个限制,我倾向于使用:

Also, because the file processing step (in this case, just a[i++]="$file", but you might want to do something fancier directly in the loop) has its input redirected, it cannot use any commands that might read from stdin. To avoid this limitation, I tend to use:

unset a i
while IFS= read -r -u3 -d $'' file; do
    a[i++]="$file"        # or however you want to process each file
done 3< <(find /tmp -type f -print0)

...通过单元 3 传递文件列表,而不是标准输入.

...which passes the file list via unit 3, rather than stdin.

这篇关于捕获 find 的输出.-print0 到 bash 数组中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆