收集文件名的bash脚本似乎被空格混淆了

时间:2012-02-29 11:23:56

标签: linux bash shell grep whitespace

我正在尝试构建一个脚本,列出一组目录中的所有zip文件,使用一些过滤器并将其吐出到文件但是当文件名中有空格时,它似乎出现在新行。

此列表最终将用作tar的输入以gzip压缩所有zip文件,脚本如下:

#!/bin/bash
rm -f set1.txt

rm -f set2.txt

for line in $(find /home -type d -name assets ;); 

do 

    echo $line >> set1.txt

    for line in $(find $line -type f -name \*.zip -mtime +2  ;);

    do

        echo \"$line\"  >> set2.txt     

    done; 

这将按预期工作,直到您在文件名中获得空格,然后set2.txt包含如下条目:

"/home/xxxxxx/oldwebroot/htdocs/upload/assets/jobbags/rbjbCost"

"in"

"use"

"sept"

"2010.zip"

有没有人知道如何让这些文件名用空格保存在一行中,整个批次包含在一组引号中?

谢谢!

2 个答案:

答案 0 :(得分:4)

通过find循环遍历一组文件的正确方法是使用while读取构造,因此:

while IFS= read -r  -d '' line ; do
    echo "$line" >> set1.txt
    while IFS= read -r -d '' file ; do
            printf '"%s"\n' "$file" >> set2.txt
    done < <(find "$line" -type f -name \*.zip -mtime +2 -print0)
done < <(find /home -type d -name assets -print0)

为清楚起见,我给了内部循环变量一个不同的名称。

如果您没有bash,则必须单独发出find命令并将输出重定向到文件,然后使用while read ; do .. done < filename读取文件。

请注意,每个变量的每次扩展都是双引号。这是必要的。

另请注意,如果您有GNU -printf,那么您可以根据需要使用find切换到find

find /home -type f -path '*/assets/*.zip' -mtime +2 -printf '"%p"\n' > set2.txt

虽然如@sarnold所说,但这并不安全。

答案 1 :(得分:1)

您应该通过其他机制执行tar(1)命令; find(1)程序支持-print0选项请求ASCII NUL - 分隔文件名输出,xargs(1)程序支持-0选项告诉输入由ASCII NUL个字符分隔。 (由于NUL是文件名中唯一不允许的字符,因此这是获得可靠文件名处理的唯一方法。)

只需使用-print0-0选项帮助,但这仍然会让脚本对另一个问题开放 - xargs(1)可能决定执行{ {1}}命令两次,三次或更多次,具体取决于其输入。 最后执行是“赢”的,而早期调用的数据将永远丢失。 (这对备份来说没用。)

因此,您还应该考虑将tar(1)命令行选项添加到--concatenate,以便它添加到存档。通过tar(1)gzip(1)添加所有文件之后执行压缩可能是有意义的。 (这确实意味着您需要在此脚本的“全新运行”之前删除存档。)