2012-12-18 29 views
89

例如,現在我用下面的方法修改了幾個文件,它們的Unix的路徑,我寫了一個文件:如何爲文件的每一行運行命令?

cat file.txt | while read in; do chmod 755 "$in"; done 

是否有一個更優雅,更安全的方法是什麼?

回答

68

如果你的文件不是太大,所有文件以及命名爲(不含空格或其他特殊字符像引號),你可以簡單地說:

chmod 755 $(<file.txt) 

如果你有特殊字符和/或很多行file.txt

xargs -0 chmod 755 < <(tr \\n \\0 <file.txt) 

如果你的命令需要通過項1的確切時間運行:

xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt) 

這是不需要這個的樣品爲chmod接受多個文件作爲參數,但這場比賽問題的標題。

對於某些特殊的情況下,你甚至可以在命令generateds通過xargs定義文件參數的位置:

xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt) 
+3

由於'xargs'是initialy build爲了回答這種需求,一些特性,比如*儘可能在當前環境中*構建命令*儘可能少地調用'chmod',減少*叉*確保效率。 'while; do..done <$ file' implie爲1個文件運行1個分支。 'xargs'可以以可靠的方式運行一千個文件。 –

+1

爲什麼第三個命令不能在makefile中工作?我得到了「意外令牌附近的語法錯誤'<'」,但直接從命令行執行。 –

+2

這似乎與Makefile特定的語法有關。您可以嘗試反轉命令行:'cat file.txt | tr \\ n \\ 0 | xargs -0 -n1 chmod 755' –

88

是的。

while read in; do chmod 755 "$in"; done < file.txt 

這樣你就可以避開cat的過程。

cat對於這樣的目的幾乎總是不好的。你可以閱讀更多關於Useless Use of Cat.

+0

避免*一個*'貓'是一個好主意,但在這種情況下** **指示的命令是'xargs' –

+0

該鏈接似乎不相關,也許網頁的內容改變了?其餘的答案是真棒,但:) :) – starbeamrainbowlabs

+0

@starbeamrainbowlabs是的。似乎頁面已被移動。我已經重新關聯,現在應該可以。謝謝:) –

9

,如果你有一個很好的選擇(例如在目錄中的所有.txt文件) 你可以這樣做:

for i in *.txt; do chmod 755 "$i"; done 

bash for loop

或變體你的:

while read line; do chmod 755 "$line"; done <file.txt 
+0

不行的是,如果行中有空格,則輸入被空格分隔,而不是按行分隔。 –

9

如果你知道你在輸入中沒有任何空格:

xargs chmod 755 < file.txt 

如果有可能在路徑的空白,如果你有GNU xargs的:

tr '\n' '\0' < file.txt | xargs -0 chmod 755 
+0

我知道xargs,但(可惜)似乎不如bash內置的功能,如while和read可靠的解決方案。另外,我沒有GNU xargs,但是我使用的是OS X,xargs在這裏也有-0選項。感謝你的回答。 – hawk

+1

@hawk否:'xargs'健壯。這個工具是非常古老的,他的代碼強烈*重訪*。他的目標最初是爲了在殼體限制(64kchar /線或其他)上建立線條。現在這個工具可以處理非常大的文件,並且可以減少fork到最終命令的數量。請參閱[我的回答](http://stackoverflow.com/a/13941223/1765658)和/或「man xargs」。 –

+0

@hawk更少的可靠的解決方案?如果它在Linux,Mac/BSD和Windows(是的,MSYSGIT的捆綁GNU xargs)中起作用,那麼它就像它可靠一樣。 –

2

我看到你所標記的bash,但Perl的也將是這樣做的好方法:

perl -p -e '`chmod 755 $_`' file.txt 

你也可以申請一個正則表達式來確保你得到正確的文件,例如只處理.txt文件:

perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt 

要「預覽」發生了什麼事,只需更換用雙引號反引號和前面加上print

perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt 
+2

爲什麼使用反引號? Perl有一個['chmod'函數](http://perldoc.perl.org/functions/chmod.html) –

+0

我沒有意識到這一點。感謝您指出:) –

+1

您希望'perl -lpe'chmod 0755,$ _'file.txt' - 使用'-l'作爲「auto-chomp」功能 –

7

如果你想在每行平行運行命令,你可以使用GNU Parallel

parallel -a <your file> <program> 

文件的每一行都會作爲參數傳遞給程序。默認情況下,parallel可以運行與CPU數量相同的線程數。但你可以指定它-j