x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
当前回答
如果使用grep而不是find呢?
ls | grep .txt$ > out.txt
现在您可以读取这个文件,文件名以列表的形式出现。
其他回答
(更新到包括@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"
' {} \;
如果使用grep而不是find呢?
ls | grep .txt$ > out.txt
现在您可以读取这个文件,文件名以列表的形式出现。
我喜欢使用find,这是第一次分配给变量和IFS切换到新行如下:
FilesFound=$(find . -name "*.txt")
IFSbkp="$IFS"
IFS=$'\n'
counter=1;
for file in $FilesFound; do
echo "${counter}: ${file}"
let counter++;
done
IFS="$IFSbkp"
正如@Konrad Rudolph所评论的那样,这将不适用于文件名中的“新行”。我仍然认为它很方便,因为它涵盖了需要遍历命令输出的大多数情况。
我认为使用这段代码(在while done之后使用管道命令):
while read fname; do
echo "$fname"
done <<< "$(find . -name "*.txt")"
比这个答案更好,因为while循环是在子shell中执行的,如果你使用这个答案,并且在while循环之后,如果你想修改循环中的变量,就不能看到变量的变化。
你可以存储你的查找输出在数组中,如果你希望以后使用输出:
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输出。