2012-09-12 159 views
3

我想了解管道和重定向命令的真正威力。根據我的理解,|將一個命令結果的輸出作爲自身的輸入。而且,>是幫助輸出重定向。如果是這樣,瞭解管道和重定向命令

find . -name "*.swp" | rm 
find . -name "*.swp" > rm 

爲什麼預期。對於我這個命令是行不通的上述命令意味着

  1. 遞歸擴展名爲找到的所有文件。在當前目錄下的swp。
  2. 1.的輸出並刪除所有的結果文件。

僅供參考,是的,我知道如何完成這項任務。它可以通過傳遞-exec標誌來完成。

find . -name "*.swp"-exec rm -rf {} \; 

但正如我已經提到的,我想用>|命令來完成它。
如果我錯了,走錯了方向,請糾正我並解釋重定向和管道命令。我們在哪裏使用其命令?請不要提及簡單的書籍例子,我讀了所有的東西。試着向我解釋一些複雜的事情。

+0

'>'是輸出重定向。 '<是輸入重定向。 – chepner

+3

你被困在標準輸入和命令行之間的區別。你想在bash中使用'$()'運算符,或者在find中使用'-exec'選項,或者(也許是你最好的選擇)'xargs'。沒有能量寫出真正的答案... – dmckee

回答

4

我會打破這種下跌已顯示的三種方法:

  • >將所有輸出重定向從find到一個名爲rm(將無法工作文件,因爲你只是追加到一個文件)。
  • find
  • |將輸出管進入rm命令(將不起作用,因爲rm不上stdin讀取)
  • -exec rm -rf {} \;將在每個項目上運行rm -rf{}),該find的發現(將工作,因爲它通過文件作爲參數rm)。

你將要使用-exec標誌,或管道進入xargs命令(man xargs),不|>,以達到所期望的行爲。

編輯:爲@dmckee說,你也可以使用$()操作字符串插值算法,即:rm -rf $(find . -name "*.swp")(如果您有大量的文件,由於參數長度的限制,這將失敗)。

+0

你也可以使用shell globbing('rm -rf **/*。swp')來實現你陳述的(例子)目標,但有點超出問題的範圍(shell管道和重定向)。 – neersighted

+0

字符串插值正在將標準輸出更改爲標準輸入,是這樣的。 –

+0

@親愛的:不,它不是。在啓動程序之前,你的shell會看到'$()',並用'$()'中的命令輸出替換它。一個例子說明了這一點。 如果我有'echo'foo $(echo'bar')「',shell會替換'$()',並真正執行'echo」foobar「'。 – neersighted

1

你應該花一些時間和再次讀到殼重定向的基礎知識:)我認爲這是一個很好的文件:http://wiki.bash-hackers.org/howto/redirection_tutorial

我會盡力解釋了什麼問題你:

find . -name "*.swp" | rm 

該命令將查找結果(即find的stdout)重定向到程序rmstdin。但是,rm未在標準輸入讀取(這是您可以在rm的文檔中閱讀的內容)。通過命令行參數控制rm,而不是通過stdin控制。我認爲根本沒有辦法從stdin中讀取rm。這就是爲什麼沒有被刪除。

find . -name "*.swp" > rm 

此命令會將新行分隔的查找結果(找到的標準輸出)到名爲「RM」的文件。同樣,沒有被刪除:)

基本上<>>>&>&>>運營商從/到文件,實際上在文件系統中存在執行重定向。管道|將一個命令的標準輸出重定向到另一個命令的標準輸入。簡單地說,這裏沒有涉及任何文件。然而,這種方法只有在管道左側的程序實際寫入stdout並且管道右側的程序從stdin兩個程序彼此理解,即讀取程序(消費者)瞭解餵養計劃的輸出。

3

>只是重定向到一個名爲rm的文件。 通過|管道到rm不起作用,因爲rm不期望通過STDIN的文件名。 所以,你必須使用xargs的,它從STDIN傳遞值作爲參數:

find . -name "*.swp"|xargs rm 

這是危險的,因爲文件名可能包含你的shell認爲一個場分隔符($ IFS)字符。 所以,你使用:

find . -name "*.swp" -print0|xargs -0 rm 

導致發現打印sperated到標準輸出文件名\ 0和xargs的讀\ 0分隔的文件名,並將其作爲參數傳遞給RM。

當然,實現這一目標的最簡單的方法將是:

rm **/*.swp 

假設你使用bash。

+0

+1,謝謝你解釋xargs。 –

0

重定向創建一個文件。因此,您的>rm示例僅創建一個名爲./rm的文件,將命令的輸出保存到該文件中。

管道本質上是一種速記。 one | twoone >tmp; two <tmp類似,但沒有(顯式)臨時文件。

當然,rm不從標準輸入讀取文件名,所以cmd | rm根本沒用(距情況下的管道與不與rm沒看過的東西輸入另一個命令繼續)。如果你想要的話,有xargs

find . -name "*.swp" | xargs rm