“find”命令不返回类似数组的元素,如何解决此问题

“find”命令不返回类似数组的元素,如何解决此问题

在 powershell 中我习惯做这样的事情:

> $python_files = get-childitem *.py
> echo $python_files[0]

第二个命令允许我提取第一个文件,因为get-childitem返回一个类似数组的对象。

在 bash 中,我知道以下内容大致相同:

> test=$(find . -iname '*.py')

然而,当我echo $test[0]没有得到第一项时,所以我认为find返回一个类似字符串的对象。

是否有一种通用方法可以从命令中获取第一项find?我所说的通用是指与命令无关的,或者可以与其他命令(例如grep.

答案1

在 bash 中,我知道以下内容大致相同:

test=$(find . -iname '*.py')

然而,当我echo $test[0]没有得到第一项时,所以我认为 find 返回一个类似字符串的对象。

对于“大致”的某些值。实际上,“大致”的值相当粗略。

管道和命令替换依赖于读取命令的输出(标准输出、stdout),这是类似文件的对象(当然它不可查找,即随机访问)。这是一个字节流。它不允许传输数据结构,除非以某种方式将它们序列化为字节序列

您要做的test=$(find . -iname '*.py')是要求find打印文件名,每行一个,然后让 shell 将其作为字符串读入变量test。该变量将包含类似 的内容hello.txt<newline>there.txt。在一定程度上这是可以的,但它不是 shell 数组,因此您无法对其进行索引,并且如果文件名包含换行符,它就会中断。(此外,如果文件名包含空格for f in $(find...),也会中断,因为这是一个不同的场景,并且其中会涉及分词。)

如果你想将 的输出读find入 Bash 中的数组中,你可以使用readarray进程替换(这个<(...)东西):

readarray -d '' -t files < <(find ... -print0)
printf '%s\n' "Third element of array is '${files[2]}'"

-print0告诉find在输出中用 NUL 字节终止每个文件名:因为这是唯一不能出现在文件名中的字节,所以它适用于明确的序列化。-d ''告诉readarray我们期望 NUL 作为分隔符。注意数组索引从在 Bash 中(参见http://mywiki.wooledge.org/BashGuide/Arrays)。

(至于可移植性:并非所有 shell 都支持数组,虽然 zsh 也支持数组,但它们的行为略有不同。-print0也不是标准的,但得到了广泛支持。)

或者,如果您只想要与 shell glob 匹配的文件列表:

files=( *.py )

(需要注意的是,如果没有匹配的文件,除非您设置该选项,否则bash您将得到一个被调用的元素)。*.pynullglob

在这里,您可以使用globstar、或dotglob其他extglob任何选项,但是您拥有的选项当然取决于 shell,并且与find给出的选项不同。

相关内容