猿问

请问如何循环查找返回的文件名?

如何循环查找返回的文件名?

x=$(find . -name "*.txt")echo $x

如果我在Bashshell中运行上面的代码,我得到的是一个包含几个文件名的字符串,该字符串由空白分隔,而不是一个列表。

当然,我可以用空白将它们分开,以获得一个列表,但我确信有更好的方法。

那么,循环遍历find指挥部?


炎炎设计
浏览 456回答 3
3回答

ITMISS

如果你只是为了最正确的答案而来,你可能想要我个人的偏好,find . -name '*.txt' -exec process {} \;(见这篇文章的底部)。如果你有时间的话,把剩下的部分读一遍,看看几种不同的方法,以及它们中大多数的问题。完整的答案是:最好的方法取决于你想做什么,但这里有几个选择。只要子树中没有文件或文件夹的名称中有空格,您就可以遍历这些文件:for&nbsp;i&nbsp;in&nbsp;$x;&nbsp;do&nbsp;#&nbsp;Not&nbsp;recommended,&nbsp;will&nbsp;break&nbsp;on&nbsp;whitespace &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;"$i"done稍微好一点,去掉临时变量x:for&nbsp;i&nbsp;in&nbsp;$(find&nbsp;-name&nbsp;\*.txt);&nbsp;do&nbsp;#&nbsp;Not&nbsp;recommended,&nbsp;will&nbsp;break&nbsp;on&nbsp;whitespace &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;"$i"done它是多你最好在可能的时候笑一笑。空白保险箱,用于当前目录中的文件:for&nbsp;i&nbsp;in&nbsp;*.txt;&nbsp;do&nbsp;#&nbsp;Whitespace-safe&nbsp;but&nbsp;not&nbsp;recursive. &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;"$i"done通过启用globstar选项,您可以在此目录和所有子目录中显示所有匹配的文件:#&nbsp;Make&nbsp;sure&nbsp;globstar&nbsp;is&nbsp;enabledshopt&nbsp;-s&nbsp;globstarfor&nbsp;i&nbsp;in&nbsp;**/*.txt;&nbsp;do&nbsp;#&nbsp;Whitespace-safe&nbsp;and&nbsp;recursive &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;"$i"done在某些情况下,例如,如果文件名已经在文件中,则可能需要使用read:#&nbsp;IFS=&nbsp;makes&nbsp;sure&nbsp;it&nbsp;doesn't&nbsp;trim&nbsp;leading&nbsp;and&nbsp;trailing&nbsp;whitespace#&nbsp;-r&nbsp;prevents&nbsp;interpretation&nbsp;of&nbsp;\&nbsp;escapes.while&nbsp;IFS=&nbsp;read&nbsp;-r&nbsp;line;&nbsp;do&nbsp;#&nbsp;Whitespace-safe&nbsp;EXCEPT&nbsp;newlines &nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;"$line"done&nbsp;<&nbsp;filenameread可安全结合使用find通过适当设置分隔符:find&nbsp;.&nbsp;-name&nbsp;'*.txt'&nbsp;-print0&nbsp;|&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;IFS=&nbsp;read&nbsp;-r&nbsp;-d&nbsp;''&nbsp;line;&nbsp;do&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;process&nbsp;$line&nbsp;&nbsp;&nbsp;&nbsp;done对于更复杂的搜索,您可能需要使用find,不管是用它-exec选项或有-print0 | xargs -0:#&nbsp;execute&nbsp;`process`&nbsp;once&nbsp;for&nbsp;each&nbsp;filefind&nbsp;.&nbsp;-name&nbsp;\*.txt&nbsp;-exec&nbsp;process&nbsp;{}&nbsp;\;#&nbsp;execute&nbsp;`process`&nbsp;once&nbsp;with&nbsp;all&nbsp;the&nbsp;files&nbsp;as&nbsp;arguments*:find&nbsp;.&nbsp;-name&nbsp;\*.txt&nbsp;-exec&nbsp;process&nbsp;{}&nbsp;+#&nbsp;using&nbsp;xargs*find&nbsp;.&nbsp;-name&nbsp;\*.txt&nbsp;-print0&nbsp;|&nbsp;xargs&nbsp;-0&nbsp;process#&nbsp;using&nbsp;xargs&nbsp;with&nbsp;arguments&nbsp;after&nbsp;each&nbsp;filename&nbsp;(implies&nbsp;one&nbsp;run&nbsp;per&nbsp;filename)find&nbsp;.&nbsp;-name&nbsp;\*.txt&nbsp;-print0&nbsp;|&nbsp;xargs&nbsp;-0&nbsp;-I{}&nbsp;process&nbsp;{}&nbsp;argumentfind还可以在运行命令之前将CD光盘到每个文件的目录中。-execdir而不是-exec,并且可以使用以下命令进行交互(在运行每个文件的命令之前提示符)-ok而不是-exec(或-okdir而不是-execdir).*:技术上,两者都是find和xargs(默认情况下)将在命令行中使用尽可能多的参数来运行该命令,并尽可能多地运行该命令以获得所有文件。实际上,除非您有大量的文件,否则这并不重要,而且如果您超过了长度,但是需要在同一个命令行中所有这些文件,你是索尔找个不同的方法。

偶然的你

find&nbsp;.&nbsp;-name&nbsp;"*.txt"|while&nbsp;read&nbsp;fname;&nbsp;do &nbsp;&nbsp;echo&nbsp;"$fname"done注:此方法和bmarguies显示的(第二个)方法在文件/文件夹名称中的空白中使用是安全的。为了在所涵盖的文件/文件夹名称中有一些异国情调的换行符,您将不得不求助于-exec谓语find就像这样:find&nbsp;.&nbsp;-name&nbsp;'*.txt'&nbsp;-exec&nbsp;echo&nbsp;"{}"&nbsp;\;这个{}是已找到项的占位符,而\;用于终止-exec谓词为了完整起见,让我添加另一个变体-你必须喜欢*nix方式,因为它们的多功能性:find&nbsp;.&nbsp;-name&nbsp;'*.txt'&nbsp;-print0|xargs&nbsp;-0&nbsp;-n&nbsp;1&nbsp;echo这将印刷品与\0据我所知,在任何文件系统中都不允许使用文件名或文件夹名中的字符,因此应该涵盖所有的基础。xargs然后一个接一个地捡起来.。

交互式爱情

不管你做什么,不要使用for环路:#&nbsp;Don't&nbsp;do&nbsp;thisfor&nbsp;file&nbsp;in&nbsp;$(find&nbsp;.&nbsp;-name&nbsp;"*.txt")do &nbsp;&nbsp;&nbsp;&nbsp;…code&nbsp;using&nbsp;"$file"done三个原因:如果for循环甚至要启动,则find必须完成。如果一个文件名中有任何空格(包括空格、制表符或换行符),那么它将被视为两个单独的名称。尽管现在不太可能,但您可以溢出命令行缓冲区。假设您的命令行缓冲区包含32 KB,而您的for循环返回40 kb的文本。最后的8KB将从你的for循环你永远也不会知道。始终使用while read建造:find&nbsp;.&nbsp;-name&nbsp;"*.txt"&nbsp;-print0&nbsp;|&nbsp;while&nbsp;read&nbsp;-d&nbsp;$'\0'&nbsp;filedo &nbsp;&nbsp;&nbsp;&nbsp;…code&nbsp;using&nbsp;"$file"done循环将在find命令正在执行。此外,即使返回带有空格的文件名,该命令也能工作。并且,您不会溢出命令行缓冲区。这个-print0将使用NULL作为文件分隔符,而不是换行符,-d $'\0'读取时将使用NULL作为分隔符。
随时随地看视频慕课网APP
我要回答