在Bash中循环遍历包含空格的文件名的find输出
在Bash中循环遍历包含空格的文件名的find输出
我试图搜索可能包含空格的文件,我尝试使用-print0
并设置IFS
,以下是我的脚本:
IFS=$'\0';find people -name '*.svg' -print0 | while read file; do
grep '
done
我试图找到包含嵌入图像的所有svg文件,如果没有使用-print0它可以工作,但是有一个文件失败了,所以我停止了脚本。这是一个不工作的简单示例:
IFS=$'\0';find . -print0 | while read file; do echo $file; done
它没有显示任何内容。
问题的原因是在使用Bash的find
命令遍历文件时,如果文件名包含空格,会导致read
命令无法正确读取文件名。解决方法是使用read -d '' -r file
命令,并且仅在read
命令的上下文中设置IFS
。此外,还需要对变量进行引用。
具体的解决方法如下所示:
find people -name '*.svg' -print0 | while IFS= read -d '' -r file; do grep '<image' "$file" > /dev/null && echo "$file" | tee -a embeded_images.txt; done
为什么read -d'' -r file; do
不起作用,但是加上空格的-d ''
却可以起作用呢?
原因是单引号中的内容为空。Bash将-d''
视为一个参数。当执行引号删除时,除了-d
之外什么都没有了。而-d ''
被视为两个参数,其中一个为null。
循环遍历Bash中包含空格的文件名输出的问题是由于在循环中创建了子shell导致的。这会导致无法在循环中设置任何变量。为了解决这个问题,可以考虑使用进程替代(process substitution)。
具体解决方法如下:
while IFS= read -d '' -r file; do grep '/dev/null && echo "$file" | tee -a embeded_images.txt done < <(find people -name '*.svg' -print0)
上述代码中,第一个`<`表示从一个文件中读取输入,而`<(find...)`则被替换为一个返回`find`命令输出的文件名(通常是一个管道句柄)。由于`while`从文件而不是管道中读取,因此循环可以设置在作用域外访问的变量。