捕获查找的输出。-print0进入bash数组

捕获查找的输出。-print0进入bash数组

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

但是,我很难让find的输出在bash或其他命令行实用程序中有用。我设法使用输出的唯一方法是将它传递给perl,并将perl的IFS更改为null:

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

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

find . | wc -l

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

我怎样才能做到这一点?

这不起作用:

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

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


慕标5832272
浏览 564回答 3
3回答

繁华开满天机

Greg的BashFAQ无耻地偷走了:unset&nbsp;a&nbsp;iwhile&nbsp;IFS=&nbsp;read&nbsp;-r&nbsp;-d&nbsp;$'\0'&nbsp;file;&nbsp;do &nbsp;&nbsp;&nbsp;&nbsp;a[i++]="$file"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;or&nbsp;however&nbsp;you&nbsp;want&nbsp;to&nbsp;process&nbsp;each&nbsp;filedone&nbsp;<&nbsp;<(find&nbsp;/tmp&nbsp;-type&nbsp;f&nbsp;-print0)请注意,此处使用的重定向构造(cmd1 < <(cmd2))与更常用的管道(cmd2 | cmd1)相似但不完全相同- 如果命令是shell内置的(例如while),管道版本在子shell中执行它们,以及它们设置的任何变量(例如阵列a)在退出时丢失。&nbsp;cmd1 < <(cmd2)只在子shell中运行cmd2,因此数组将超过其构造。警告:这种重定向形式仅在bash中可用,在sh仿真模式下甚至不是bash;&nbsp;你必须用你的脚本开始#!/bin/bash。此外,因为文件处理步骤(在这种情况下,只是a[i++]="$file",但你可能想在循环中直接做一些更好的事情)将其输入重定向,它不能使用任何可能从stdin读取的命令。为了避免这种限制,我倾向于使用:unset&nbsp;a&nbsp;iwhile&nbsp;IFS=&nbsp;read&nbsp;-r&nbsp;-u3&nbsp;-d&nbsp;$'\0'&nbsp;file;&nbsp;do &nbsp;&nbsp;&nbsp;&nbsp;a[i++]="$file"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;or&nbsp;however&nbsp;you&nbsp;want&nbsp;to&nbsp;process&nbsp;each&nbsp;filedone&nbsp;3<&nbsp;<(find&nbsp;/tmp&nbsp;-type&nbsp;f&nbsp;-print0)...通过单元3传递文件列表,而不是stdin。

一只甜甜圈

也许你正在寻找xargs:find&nbsp;.&nbsp;-print0&nbsp;|&nbsp;xargs&nbsp;-r0&nbsp;do_something_useful选项-L 1对你也很有用,这使得xargs exec do_something_useful只有1个文件参数。

开心每一天1111

主要问题是,分隔符NUL(\ 0)在这里没用,因为不可能为IFS分配NUL值。因此,作为优秀的程序员,我们需要注意的是,我们程序的输入是它能够处理的。首先,我们创建一个小程序,为我们完成这一部分:#!/bin/bashprintf&nbsp;"%s"&nbsp;"$@"&nbsp;|&nbsp;base64...并将其命名为base64str(不要忘记chmod + x)其次,我们现在可以使用一个简单而直接的for循环:for&nbsp;i&nbsp;in&nbsp;`find&nbsp;-type&nbsp;f&nbsp;-exec&nbsp;base64str&nbsp;'{}'&nbsp;\;`do&nbsp; &nbsp;&nbsp;file="`echo&nbsp;-n&nbsp;"$i"&nbsp;|&nbsp;base64&nbsp;-d`" &nbsp;&nbsp;#&nbsp;do&nbsp;something&nbsp;with&nbsp;filedone所以诀窍是,base64-string没有任何迹象会导致bash出现问题 - 当然xxd或类似的东西也可以完成这项工作。
打开App,查看更多内容
随时随地看视频慕课网APP