x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
当前回答
你可以存储你的查找输出在数组中,如果你希望以后使用输出:
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,这是第一次分配给变量和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所评论的那样,这将不适用于文件名中的“新行”。我仍然认为它很方便,因为它涵盖了需要遍历命令输出的大多数情况。
(更新到包括@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"
' {} \;
你可以把find返回的文件名放入这样一个数组:
array=()
while IFS= read -r -d ''; do
array+=("$REPLY")
done < <(find . -name '*.txt' -print0)
现在,您可以循环遍历数组以访问单个项,并对它们做任何您想做的事情。
注意:它是空白安全的。
# Doesn't handle whitespace
for x in `find . -name "*.txt" -print`; do
process_one $x
done
or
# Handles whitespace and newlines
find . -name "*.txt" -print0 | xargs -0 -n 1 process_one
无论你做什么,都不要使用for循环:
# Don't do this
for file in $(find . -name "*.txt")
do
…code using "$file"
done
三个原因:
为了使For循环开始,find必须运行到完成。 如果一个文件名中有任何空格(包括空格、制表符或换行符),它将被视为两个独立的名称。 虽然现在不太可能,但您可以溢出命令行缓冲区。想象一下,如果您的命令行缓冲区有32KB,而for循环返回40KB的文本。最后的8KB将从for循环中删除,而您永远不会知道。
总是使用while read结构:
find . -name "*.txt" -print0 | while read -d $'\0' file
do
…code using "$file"
done
循环将在执行find命令时执行。另外,即使返回的文件名中有空格,该命令也可以工作。而且,不会溢出命令行缓冲区。
print0将使用NULL作为文件分隔符而不是换行符,而-d $'\0'将在读取时使用NULL作为分隔符。