題 如何將命令輸出傳遞給其他命令?


例:

ls | echo 什麼都不打印(實際上是空行)。我希望它能打印一份文件列表。

ls | grep 'foo'另一方面,按預期工作(打印名稱中帶有'foo'的文件)。

在這些情況下我做的是:       ls | while read OUT; do echo $OUT; done 但這很麻煩。

為什麼管道使用某些命令,而不是其他命令?我該如何規避這個問題?


78
2017-09-16 13:40


起源


你能指望什麼 ls | echo 去做?為什麼不簡單地跑 ls? - theomega
我用最簡單的例子說明了我的觀點。當我試圖製作一個可以在對象存儲中顯示git對象及其類型的單行時,我實際上遇到了這個問題。所以,我將對象ID傳遞給了 git cat-file,但它只是沒有用。顯然,echo具有相同的行為,所以我用它作為例子。 - Mihai Rotaru
另外看一下xargs的-n命令,它說明了在子命令上放了多少個參數。 `... | xargs -n1 git cat-file` - Rich Homolka


答案:


命令行參數和標準輸入之間存在區別。管道將一個過程的標準輸出連接到另一個過程的標準輸入。所以

ls | echo

將ls的標準輸出連接到echo的標準輸入。好吧?好吧,echo忽略了標準輸入,並將其命令行參數(在本例中為none)轉儲到它自己的stdout。輸出:什麼都沒有。

在這種情況下有一些解決方案。一種是使用一個命令來讀取stdin並轉儲到stdout,例如cat。

ls | cat

將“工作”,取決於您的工作定義。

但是一般情況呢?你真正想要的是將一個命令的stdout轉換為另一個命令的命令行args。正如其他人所說, xargs 在這種情況下,是規範的幫助工具,從其stdin讀取命令行args以及構造要運行的命令。

ls | xargs echo

您也可以使用substitution命令將其轉換為一些 $()

echo $(ls)

也會做你想要的。

這兩個工具都是shell腳本的核心,你應該學習它們。

為了完整性,正如您在問題中指出的那樣,將stdin轉換為命令行參數的另一種基本方法是shell的內置 read 命令。它轉換“單詞”(由單詞定義的單詞) IFS 變量)到臨時變量,可以在任何命令運行中使用。


109
2017-09-16 14:16



一個非常有用的信息答案,謝謝!我正在學習bash,我之前看過xargs和$(*)表示法,但沒注意它們。現在我知道它們有多重要,並且一定會調查它們。 - Mihai Rotaru
xargs可能是OP正在尋找的東西。 - Iktys


ls | echo 打印只是一個空白行,因為 echo 沒有輸入;管道的最後一個命令實際上是 echo 只打印一條空行。

通常:

a | b

確保輸出 a 成為的輸入 b。我建議你看看 Pipelines 部分 man bash


如果你真的想用 ls 和 echo 這裡有一些(相當無用的)例子:

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done

16
2017-09-16 13:54





如果你想 echo 該 ls 命令嘗試:

ls | xargs echo

這會打電話 echo 與輸出 ls


7
2017-09-16 14:03



要么 ls | xargs -I {} echo {} 如果你想單獨為每一行調用它 - Alex Abdugafarov


為什麼不簡單地使用:

echo `ls`

或者更安全:

echo "`ls -lrt`"

3
2017-11-09 09:48



甚至只是 echo *。 - Kazark