2009-11-06 76 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