2009-11-06 72 views
28

我试图写一个bash脚本,将处理的文件,其名称都存储每行一个输入文件,东西如何从bash中的文件读取文件名列表?

find . -type f -mtime +15 > /tmp/filelist.txt 
for F in $(cat /tmp/filelist.txt) ; do 
    ... 
done; 

我的问题喜欢的列表是Filelist.txt中的文件名可以包含空格,因此上述剪断将扩大线

my text file.txt 

到三个不同的文件名,mytextfile.txt。我该如何解决这个问题?

+1

要知道,目录项也可以包含换行符,以及作为空间和其他古怪的角色。目录条目(文件名)不能有唯一的东西是“/”和“”字符。 (斜杠和空)。 – chris 2009-11-06 17:51:53

+0

是的,但我正在处理的文件是由我的局域网上的Windows用户访问samba共享创建的,所以文件名奇怪有一个限制 – agnul 2009-11-06 18:23:39

回答

36

使用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选项运行,如果每个文件直接找到。

+0

虽然我投了票,但我发现这个脚本在包含非ASCII字符的路径上失败。 – kakyo 2013-11-10 19:11:50

-1

我相信你可以完全跳过临时文件和刚刚超过找到的结果直接循环,即:

for F in $(find . -type f -mtime +15) ; do 
    ... 
done; 

不保证我的语法是正确的,但我敢肯定的概念作品。

编辑:如果您确实需要使用文件名列表来处理文件,并且不能像上面那样简单地组合命令,那么您可以更改IFS变量的值 - 它代表内部字段分隔符 - 改变bash如何确定字段。默认情况下,它被设置为空格,所以换行符,空格或制表符将开始一个新字段。如果您将其设置为只包含换行符,那么您可以像以前一样遍历该文件。

+1

我认为shell仍然会在空格上做分离? – 2009-11-06 17:23:59

+0

请注意这一点 - 它与原始版本存在相同的问题(拆分空格) – DVK 2009-11-06 17:25:31

+0

我做了一个编辑,不得不在中间接电话,但我估计5分钟太长,无法在此站点上等待。 – qid 2009-11-06 17:32:21

3

使用,而读

echo $FILE | while read line 
do 
echo $line 
done 

你可以做重定向,而不是回声

+0

如果你只有一个文件,那么shell重定向避免产生一个'cat'进程。 – 2009-11-06 17:27:25

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 
1

你可以使用的-exec参数find和直接使用的文件名:

find . -type f -mtime +15 -exec <your command here> {} \; 

{}是文件名的占位符。

+0

问题是我没有运行一个命令,我最终会尝试所有类型的奇怪的组合,以找到正确的方式来引用和逃避后的东西--exec – agnul 2009-11-06 19:22:05

6

可以使用进程替换做到这一点没有一个临时文件:

while read F 
do 
    ... 
done < <(find . -type f -mtime +15) 
+0

整洁!不知道流程替换。 – agnul 2009-11-06 19:09:04

+1

请注意,进程替换功能是bash扩展,甚至在sh兼容模式下甚至不可用于bash。你必须用'#!/ bin/bash'开始你的脚本才能工作。顺便说一句,我还建议使用'while IFS =“”read -r F'来避免文件名开头或结尾处出现空白和结尾处出现反斜线(尽管如果文件来自Windows,反斜杠可能不是可能)。 – 2009-11-06 20:19:58

1

管你find命令直在卡读取循环

find . -type f -mtime +15 | while read -r line 
do 
    printf "do something with $line\n" 
done