Zrozumienie sposobu przesyłania danych wejściowych do potoków w Bash

17

Nie do końca rozumiem, jak rury działają w trybie bash.

Wiem, że pobiera dane wyjściowe z jednego polecenia jako dane wejściowe w innym poleceniu.

Co mogę uzyskać, ponieważ to polecenie wypisuje na ekran.

Ale skąd mam wiedzieć, jakie dane wprowadzi polecenie?

Oto przykład, który moim zdaniem powinien zadziałać:

which gem | rm

Niestety tak nie było.

Który klejnot jest drukowany, /usr/bin/gemwięc musi być poprawnie wydrukowany?

Myślałem, że to zostało przekazane rm, więc będzie, rm /usr/bin/gemale się myliłem.

Więc moje pytanie brzmi: skąd mam wiedzieć, jaki wkład przyjmuje polecenie?

ajsie
źródło
2
Poza wszystkim, rm /usr/bin/gemto okropny pomysł. Zostaw to gem(i tłumacz Ruby, z którym idzie) w spokoju i zainstaluj preferowanego tłumacza (i gem) Ruby, używając rvm: rvm.beginrescueend.com
Telemachus

Odpowiedzi:

23

„Dane wejściowe” i „argumenty wiersza poleceń” to różne rzeczy.

rm usuwa pliki podane jako argumenty.

Potok przekierowuje wyjście polecenia po lewej stronie na wejście polecenia po prawej stronie. Nie wpływa na argumenty wiersza poleceń programu po prawej stronie.

Aby zrobić to, co próbujesz zrobić, spróbuj xargsprzekonwertować standardowe dane wejściowe na argumenty wiersza polecenia służące do wykonania programu. To jest jego praca.

which gem | xargs rm, na przykład, usunie gemw twojej ŚCIEŻCE.

Borealid
źródło
12

rmnie przyjmuje danych wejściowych, wymaga argumentów. Te są różne. Argumenty to przełączniki i nazwy plików itd., Które podajesz programowi w wierszu poleceń, aby wpłynąć na jego zachowanie. Dane wejściowe to dane, na których program działa. Na przykład grepbierze zarówno argumenty wejściowe, jak i argumenty:

grep "foo" file.txt

Istnieją dwa argumenty "foo"i file.txt. Wejście jest zawartość z file.txt, a nie ciąg file.txtsamego. Ponieważ grep pobiera dane wejściowe, możesz używać go z potokami:

cat file.txt | grep "foo"

wytworzy, ponieważ kot bierze file.txtjako argument i produkcji treści o file.txtjak wyjście. Dane wyjściowe są następnie przesyłane do grep, dając taki sam efekt jak otwarcie grep samego pliku, jak w pierwszym przykładzie.

Jeśli chcesz użyć danych wyjściowych jednego programu jako argumentu dla innego, użyj odwrotnych znaków:

rm `which gem`

lub ta alternatywna (specyficzna dla bash) składnia:

rm $(which gem)

Edycja: lub xargsjak wskazuje inny odpowiadający. Wiele sposobów na skórowanie kota za pomocą wiersza poleceń.

Tyler McHenry
źródło
Warto zauważyć, że cat file.txt | grep "foo"może być setki razy wolniejszy niż grep "foo" file.txt.
Borealid
1
to jest część, której nie rozumiem. skąd mam wiedzieć, co to jest argument i jakie jest standardowe wejście?
ajsie,
8
@ajsie: Jeśli wpiszesz go po nazwie programu i przed naciśnięciem enter, będzie to argument. Jeśli wpiszesz go do programu po uruchomieniu, będzie to standardowe wejście.
Borealid
1
Rozumiem! To wszystko wyjaśniło. Teraz wiem, że mogę zarówno użyć polecenia bezpośrednio i sprawdzić, czy wyświetla mi się monit (grep), a także mogłem przeczytać instrukcję (man grep), aby sprawdzić, czy używa standardowego wejścia.
ajsie,
@ajsie: Jeśli nie chcesz zagłębiać się w stronę podręcznika, istnieje również grep --helpszybki przegląd przyjętych argumentów.
Borealid
3

Sprawdź manstrony poleceń, które Cię interesują. Programy te wskażą, że czytają stdin(wypróbuj man greppopularne polecenie, które czyta standardowe wejście).

naparstek
źródło
Próbowałem man grep | grep 'standard input'i dostałem się If no file arguments are specified, the standard input is used.jako ostatni mecz. Had Musiałem greptrochę posmakować własnego leku. 😎
ma11hew28
2

Wszystkie są niebezpieczne do uruchomienia, jeśli w katalogu PATH znajduje się katalog zawierający spację lub jeśli nazwa polecenia zawiera spację:

rm `which gem`       # Dangerous
rm $(which gem)      # Dangerous
which gem | xargs rm # Dangerous

GNU Parallel http: // www.gnu.org/software/parallel/ nie ma tego problemu, więc zadziała to nawet wtedy, gdy w katalogu PATH znajduje się katalog zawierający spację lub jeśli nazwa polecenia zawiera spację:

which gem | parallel rm
parallel -a <(which bass) rm

Obejrzyj wideo wprowadzające do GNU Parallel: http://www.youtube.com/watch?v=OpaiGYxkSuQ

Ole Tange
źródło