x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
x=$(find . -name "*.txt")
echo $x
如果我在Bash shell中运行上面的代码段,我得到的是一个包含几个由空白分隔的文件名的字符串,而不是一个列表。
当然,我可以进一步用空白分隔它们以得到一个列表,但我相信有更好的方法来做到这一点。
那么,循环查找命令结果的最佳方法是什么呢?
当前回答
我认为使用这段代码(在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输出。
正如Kevin已经在上面的答案中发布的那样,最好的解决方案是使用bash glob的for循环,但由于bash glob默认情况下不是递归的,这可以通过bash递归函数来修复:
#!/bin/bash
set -x
set -eu -o pipefail
all_files=();
function get_all_the_files()
{
directory="$1";
for item in "$directory"/* "$directory"/.[^.]*;
do
if [[ -d "$item" ]];
then
get_all_the_files "$item";
else
all_files+=("$item");
fi;
done;
}
get_all_the_files "/tmp";
for file_path in "${all_files[@]}"
do
printf 'My file is "%s"\n' "$file_path";
done;
相关问题:
Bash loop through directory including hidden file Recursively list files from a given directory in Bash ls command: how can I get a recursive full-path listing, one line per file? List files recursively in Linux CLI with path relative to the current directory Recursively List all directories and files bash script, create array of all files in a directory How can I creates array that contains the names of all the files in a folder? How can I creates array that contains the names of all the files in a folder? How to get the list of files in a directory in a shell script?
如果使用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"
' {} \;
我认为使用这段代码(在while done之后使用管道命令):
while read fname; do
echo "$fname"
done <<< "$(find . -name "*.txt")"
比这个答案更好,因为while循环是在子shell中执行的,如果你使用这个答案,并且在while循环之后,如果你想修改循环中的变量,就不能看到变量的变化。