x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
当前回答
(更新到包括@Socowi的卓越速度提升)
使用任何支持它的$SHELL (dash/zsh/bash…):
find . -name "*.txt" -exec $SHELL -c '
for i in "$@" ; do
echo "$i"
done
' {} +
完成了。
原来的答案(更短,但更慢):
find . -name "*.txt" -exec $SHELL -c '
echo "$0"
' {} \;
其他回答
你可以存储你的查找输出在数组中,如果你希望以后使用输出:
array=($(find . -name "*.txt"))
现在要打印new line中的每个元素,可以使用for循环迭代数组的所有元素,也可以使用printf语句。
for i in ${array[@]};do echo $i; done
or
printf '%s\n' "${array[@]}"
你还可以使用:
for file in "`find . -name "*.txt"`"; do echo "$file"; done
这将以换行符打印每个文件名
若要仅以列表形式打印查找输出,可以使用以下方法之一:
find . -name "*.txt" -print 2>/dev/null
or
find . -name "*.txt" -print | grep -v 'Permission denied'
这将删除错误消息,并仅在新行中输出文件名。
如果您希望对文件名做一些事情,将其存储在数组中是很好的,否则不需要占用该空间,您可以直接从find输出。
find . -name "*.txt"|while read fname; do
echo "$fname"
done
注意:此方法和bmargulies所示的(第二个)方法在文件/文件夹名称中使用空白时是安全的。
为了在文件/文件夹名称中包含换行符,你必须使用find的-exec谓词,就像这样:
find . -name '*.txt' -exec echo "{}" \;
{}是找到的项的占位符,\;用于终止-exec谓词。
为了完整起见,让我添加另一个变体-你必须喜欢*nix的多功能性:
find . -name '*.txt' -print0|xargs -0 -n 1 echo
这将使用\0字符分隔打印项,据我所知,在任何文件系统的文件或文件夹名称中都不允许使用\0字符,因此应该涵盖所有基础。Xargs一个接一个地把它们捡起来,然后……
查找<path> -xdev -type f -name *.txt -exec ls -l {} \;
这将列出文件并给出有关属性的详细信息。
我认为使用这段代码(在while done之后使用管道命令):
while read fname; do
echo "$fname"
done <<< "$(find . -name "*.txt")"
比这个答案更好,因为while循环是在子shell中执行的,如果你使用这个答案,并且在while循环之后,如果你想修改循环中的变量,就不能看到变量的变化。
(更新到包括@Socowi的卓越速度提升)
使用任何支持它的$SHELL (dash/zsh/bash…):
find . -name "*.txt" -exec $SHELL -c '
for i in "$@" ; do
echo "$i"
done
' {} +
完成了。
原来的答案(更短,但更慢):
find . -name "*.txt" -exec $SHELL -c '
echo "$0"
' {} \;