我正在尝试构建一个脚本,列出一组目录中的所有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"
有没有人知道如何让这些文件名用空格保存在一行中,整个批次包含在一组引号中?
谢谢!
答案 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)
添加所有文件之后执行压缩可能是有意义的。 (这确实意味着您需要在此脚本的“全新运行”之前删除存档。)