Bash 脚本 - 迭代 find 的输出

问题描述 投票:0回答:4

我有一个 bash 脚本,我需要在其中迭代 find 命令输出的每一行,但似乎我正在迭代 find 命令中的每个单词(以空格分隔)。到目前为止我的脚本看起来像这样:

folders=`find -maxdepth 1 -type d`

for $i in $folders
do
    echo $i
done

我希望它能给出如下输出:

./dir1 and foo
./dir2 and bar
./dir3 and baz

但是我得到了这样的输出:

./dir1
and
foo
./dir2
and
bar
./dir3
and
baz

我在这里做错了什么?

linux bash shell scripting
4个回答
27
投票
folders=`foo`

总是错误的,因为它假设您的目录不会包含空格、换行符(是的,它们是有效的!)、全局字符等。一种强大的方法(需要 GNU 扩展

-print0
)如下:

while IFS='' read -r -d '' filename; do
  : # something with "$filename"
done < <(find . -maxdepth 1 -type d -print0)

另一种安全可靠的方法是让

find
本身直接调用您所需的命令:

find . -maxdepth 1 -type d -exec printf '%s\n' '{}' +

请参阅 UsingFind wiki 页面以获取对该主题的完整处理。


6
投票

由于您没有使用

find
的任何更高级功能,因此您可以使用简单的模式来迭代子目录:

for i in ./*/; do
    echo "$i"
done

2
投票

你可以这样做:

find -maxdepth 1 -type d | while read -r i
do
    echo "$i"
done

0
投票

基于 Charles Duffy 的回答(值得称赞!),我制作了一个 bash 函数

qfind
(引用的 find),它输出
find
但引用的所有输出。我正在将其添加到我的
.bashrc

qfind() {
    while IFS='' read -r -d $'\0' findOutput; do
        /usr/bin/echo -n "${findOutput@Q} "
    done < <(/usr/bin/find "$@" -print0)
}

带引号的字符串用空格分隔。

${findOutput@Q}
扩展为
${findOutput}
的引用值,就像
"$(quote "$findOutput")"
一样。当
-n
echo
中移除时,也会使用换行符进行分隔。

可以这样使用

eval "folders=($(qfind . -maxdepth 1 -type d))"
for i in "${folders[@]}"; do
    echo "$i"
done
需要

eval
来评估任何带引号的子字符串。

使用预定义函数,循环体中不会有任何其他命令在循环期间从 stdin 读取字符。

© www.soinside.com 2019 - 2024. All rights reserved.