2010-09-16 13:40:08 +0000 2010-09-16 13:40:08 +0000
88
88

Jak potokować wyjście polecenia do innych poleceń?

Przykład:

ls | echo nie wypisuje nic (właściwie pustą linię). Oczekiwałbym, że wydrukuje listę plików.

ls | grep 'foo', z drugiej strony, działa zgodnie z oczekiwaniami (wypisuje pliki z ‘foo’ w nazwie).

To co robię w takich sytuacjach to coś w stylu: ls | while read OUT; do echo $OUT; done ale jest to dość uciążliwe.

Dlaczego piping działa z niektórymi komendami, a z innymi nie ? Jak mogę obejść ten problem ?

Odpowiedzi (4)

123
123
123
2010-09-16 14:16:59 +0000

Istnieje rozróżnienie pomiędzy argumentami wiersza poleceń a standardowym wejściem. Potok połączy standardowe wyjście jednego procesu ze standardowym wejściem innego. Tak więc

ls | echo

łączy standardowe wyjście ls ze standardowym wejściem echo. Dobrze, prawda? Cóż, echo ignoruje standardowe wejście i wyrzuca swoje argumenty wiersza poleceń - które w tym przypadku są żadne - na swoje własne stdout. Wyjście: zupełnie nic.

W tym przypadku istnieje kilka rozwiązań. Jednym z nich jest użycie polecenia, które czyta stdin i wyrzuca na stdout, takiego jak cat.

ls | cat

Będzie “działać”, w zależności od tego, jaka jest twoja definicja pracy.

Ale co z ogólnym przypadkiem. To, czego naprawdę chcesz, to przekonwertować stdout jednego polecenia na argumenty wiersza poleceń innego. Jak powiedzieli inni, xargs jest kanonicznym narzędziem pomocniczym w tym przypadku, czytając swoje argumenty wiersza poleceń dla polecenia z jego stdin i konstruując polecenia do uruchomienia.

ls | xargs echo

Możesz również przekonwertować to trochę, używając polecenia podstawienia $()

echo $(ls)

Zrobiłoby to, co chcesz.

Oba te narzędzia są dość kluczowe dla skryptów powłoki, powinieneś się ich nauczyć.

Dla kompletności, jak wskazujesz w pytaniu, innym podstawowym sposobem konwersji stdin na argumenty wiersza poleceń jest wbudowane polecenie read powłoki. Konwertuje ono “słowa” (słowa zdefiniowane przez zmienną IFS) na zmienną temp, której możesz użyć w dowolnym uruchomieniu polecenia.

19
19
19
2010-09-16 13:54:37 +0000

ls | echo wypisuje tylko pusty wiersz, ponieważ echo nie czyta żadnego wejścia; ostatnim poleceniem potoku jest właściwie echo, które wypisuje tylko pusty wiersz.

Ogólnie:

a | b

dba o to, aby wyjście a stało się wejściem b. Proponuję przeczytać sekcję Pipelines w man bash.


Jeśli naprawdę chcesz używać ls i echo razem, oto kilka (całkiem bezużytecznych) przykładów:

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
13
13
13
2010-09-16 14:03:04 +0000

Jeśli chcesz echo komendę ls spróbuj:

ls | xargs echo

To wywoła echo z wyjściem ls.

3
3
3
2011-11-09 09:48:27 +0000

Dlaczego nie użyć po prostu:

echo `ls`

Albo znacznie bezpieczniej:

echo "`ls -lrt`"