BASH for循环、find与空格处理

2021年11月28日

假设当前目录下有
‘a b’
c
d
这三个文件

for f in *
do
echo $f
echo ‘next’
done

输出
a b
next
c
next
d
next

说明*可以处理空格的情况。具体来说应该是globbing和word spliting的顺序问题。

for f in “*”
do
echo $f
echo ‘next’
done
输出
*
next

这里发生了概念误用。双引号用来包变量的,包globbing会令globbing失去含义。

for f in $(find . -type f)
do
echo $f
echo ‘next’
done
输出
./a
next
b
next
./c
next
./d
next

$(find . -type f) 输出的是字符串,按默认IFS分隔。

for f in “$(find . -type f)”
do
echo $f
echo ‘next’
done

输出
./a b ./c ./d
next
说明引号把find的输出整个作为一个数组元素,虽然不分隔带空格的文件了,但所有文件名被当成一个文件名了。

for f in ( “$(find . -type f)” )
do
echo $f
echo ‘next’
done
这里发生了语法错误。
作者原意应该是用()把find的输出作为变量,再传给for。但是bash的语法没有那么强的替换性。
a=( “$(find . -type f)” )
for f in $a
do
echo $f
echo ‘next’
done

不能把the RHS of assignment直接放到for in 里面。

把find的输出放入for循环的根本问题是,文件名可以有空格,每个(带空格的)文件名用\n分隔,默认分隔符包含空格和\n。

解决方法

对文件列表的产生和对每个文件的处理进行trade off。

若要对文件有更多控制,用`find -exec`。

若要对每个文件有更多控制,用for+globbing。