我正在尝试编写一个bash脚本来处理一个文件列表,这些文件的名称在输入文件中每行存储一个,类似于
find . -type f -mtime +15 > /tmp/filelist.txt
for F in $(cat /tmp/filelist.txt) ; do
...
done;
我的问题是filelist.txt中的文件名可能包含空格,因此上面的剪切将扩展该行
my text file.txt
指向三个不同的文件名,my
,text
和file.txt
。我该如何解决这个问题?
答案 0 :(得分:41)
使用read
:
while read F ; do
echo $F
done </tmp/filelist.txt
或者使用IFS来更改shell分隔列表的方式:
OLDIFS=$IFS
IFS="
"
for F in $(cat /tmp/filelist.txt) ; do
echo $F
done
IFS=$OLDIFS
或者(正如@tangens所建议的那样),将循环体转换为单独的脚本,然后使用find
的-exec选项运行if对于直接找到的每个文件。
答案 1 :(得分:7)
您可以在没有使用进程替换的临时文件的情况下执行此操作:
while read F
do
...
done < <(find . -type f -mtime +15)
答案 2 :(得分:3)
阅读时使用
echo $FILE | while read line
do
echo $line
done
您可以重定向而不是回声
答案 3 :(得分:2)
您可以使用-exec
的{{1}}参数并直接使用文件名:
find
find . -type f -mtime +15 -exec <your command here> {} \;
是文件名的占位符。
答案 4 :(得分:1)
在读取循环时将find命令直接传送给
find . -type f -mtime +15 | while read -r line
do
printf "do something with $line\n"
done
答案 5 :(得分:0)
我无论如何都不是bash专家(我通常用ruby或python编写我的脚本来跨平台),但是在处理之前我会使用正则表达式来解除每行中的空格。
对于Bash正则表达式: http://www.linuxjournal.com/node/1006996
在Ruby中的类似情况(处理csv文件,并在使用之前清理每一行):
File.foreach(csv_file_name) do |line|
clean_line = line.gsub(/( )/, '\ ')
#this finds the space in your file name and escapes it
#do more stuff here
end
答案 6 :(得分:-1)
我相信你可以完全跳过临时文件而只是直接迭代find的结果,即:
for F in $(find . -type f -mtime +15) ; do
...
done;
不保证我的语法是正确的,但我很确定这个概念是有效的。
编辑:如果你真的必须使用文件名列表处理文件,并且不能像上面那样简单地组合命令,那么你可以改变IFS
变量的值 - 它代表用于内部字段分隔符 - 更改bash确定字段的方式。默认情况下,它设置为空白,因此换行符,空格或制表符将开始一个新字段。如果将其设置为仅包含换行符,则可以像以前一样迭代文件。