Są pewne polecenia, które filtrują lub działają na wejściu, a następnie przekazują je jako dane wyjściowe, myślę, że zwykle stdout
- ale niektóre polecenia po prostu biorą stdin
i robią to, co z nimi robią, i nie generują nic.
Najbardziej znam się na systemie OS X, dlatego od razu przychodzą mi na myśl dwa pbcopy
i pbpaste
- które umożliwiają dostęp do schowka systemowego.
W każdym razie wiem, że jeśli chcę wziąć standardowe wyjście i wypluć dane wyjściowe, aby przejść zarówno stdout
do pliku, jak i do pliku, mogę użyć tee
polecenia. I wiem trochę xargs
, ale nie sądzę, że tego właśnie szukam.
Chcę wiedzieć, jak mogę podzielić, stdout
aby przejść między dwoma (lub więcej) poleceniami. Na przykład:
cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors
Prawdopodobnie jest lepszy przykład niż ten, ale naprawdę interesuje mnie, jak mogę wysłać polecenie stdout do polecenia, które go nie przekazuje, i jednocześnie powstrzymując się stdout
od „wyciszenia” - nie pytam o to, jak cat
plik i grep
część i skopiuj go do schowka - określone polecenia nie są tak ważne.
Ponadto - nie pytam, jak wysłać to do pliku i stdout
- może to być pytanie „duplikowane” (przepraszam), ale szukałem i mogłem znaleźć tylko te podobne, które pytały o sposób podziału między stdout a plikiem - i wydawało się tee
, że odpowiedzi na te pytania są dla mnie nieskuteczne.
Na koniec możesz zapytać „dlaczego nie uczynić pbcopy ostatnią rzeczą w łańcuchu rur?” a moja odpowiedź brzmi: 1) co jeśli chcę go użyć i nadal widzieć dane wyjściowe w konsoli? 2) co jeśli chcę użyć dwóch poleceń, które nie są wypisywane stdout
po przetworzeniu danych wejściowych?
Aha, i jeszcze jedno - zdaję sobie sprawę, że mógłbym użyć tee
i nazwaną potok ( mkfifo
), ale liczyłem na sposób, w jaki można to zrobić inline, zwięźle, bez wcześniejszej konfiguracji :)
Odpowiedzi:
Możesz użyć
tee
i przetworzyć substytucję:Spowoduje to wysłanie wszystkich danych wyjściowych
cat file.txt
dopbcopy
, a wynik zostanie wyświetlony tylkogrep
na konsoli.W części można umieścić wiele procesów
tee
:źródło
pbcopy
, ale warto wspomnieć w ogóle: cokolwiek wyjścia podmiany proces jest również postrzegane przez następnego odcinka rury, po pierwotnym wejściem; np .:seq 3 | tee >(cat -n) | cat -e
(cat -n
numeruje linie wejściowe,cat -e
zaznacza nowe linie za pomocą$
; zobaczysz, żecat -e
jest to stosowane zarówno do oryginalnego wejścia (najpierw), jak i (następnie) wyjścia zcat -n
). Dane wyjściowe z wielu zastąpień procesów będą dostarczane w niedeterministycznej kolejności.>(
Tylko działabash
. Jeśli spróbujesz użyć tego na przykład,sh
to nie zadziała. Ważne jest, aby to zrobić.dash
, który działa jaksh
w systemie Ubuntu, nie obsługuje go, a nawet sama Bash dezaktywuje tę funkcję, gdy jest wywoływana wsh
trakcie lub w trakcieset -o posix
działania. Jednak nie tylko Bash obsługuje podstawienia procesów:ksh
izsh
wspiera je także (nie jestem pewien co do innych).bash
i najwyraźniej nie wysyła danych wyjściowych z podstawień procesów wyjściowych przez potok (prawdopodobnie jest to preferowane , ponieważ nie zanieczyszcza tego, co jest wysyłane do następnego segmentu potoku - chociaż nadal drukuje ). Jednak we wszystkich wspomnianych powłokach generalnie nie jest dobrym pomysłem posiadanie jednego potoku, w którym mieszane są standardowe wyjścia standardowe i wyjściowe z podstawień procesów - kolejność wyjściowa nie będzie przewidywalna, w sposób, który może pojawiać się rzadko lub z dużą zestawy danych wyjściowych.ksh
zsh
Możesz podać wiele nazw plików
tee
, a ponadto standardowe wyjście można połączyć w jedno polecenie. Aby wysłać dane wyjściowe do wielu poleceń, musisz utworzyć wiele potoków i określić każde z nich jako jedno wyjścietee
. Można to zrobić na kilka sposobów.Zastąpienie procesu
Jeśli twoją powłoką jest ksh93, bash lub zsh, możesz użyć podstawienia procesu. Jest to sposób na przekazanie potoku do polecenia, które oczekuje nazwy pliku. Powłoka tworzy potok i przekazuje nazwę pliku podobną
/dev/fd/3
do polecenia. Liczba jest deskryptorem pliku , do którego podłączony jest potok. Niektóre warianty uniksowe nie obsługują/dev/fd
; na nich używany jest nazwany potok (patrz poniżej).Deskryptory plików
W dowolnej powłoce POSIX można jawnie używać wielu deskryptorów plików . Wymaga to obsługiwanego wariantu unix
/dev/fd
, ponieważ wszystkie wyjścia oprócz jednegotee
muszą być określone według nazwy.Nazwane rury
Najbardziej podstawową i przenośną metodą jest użycie nazwanych potoków . Minusem jest to, że musisz znaleźć katalog do zapisu, utworzyć potoki, a następnie wyczyścić.
źródło
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
powinieneś na pewno byćcommand3 | tee "$tmp_dir/f1" "$tmp_dir/f2"
, jak chcesz stdout zcommand3
ruramitee
, nie? Przetestowałem twoją wersję poddash
itee
blokuje się w nieskończoność, czekając na dane wejściowe, ale zmiana kolejności dała oczekiwany rezultat.command
,command2
icommand3
.<command> | bash -c 'tee >(command1) >(command2) | command3'
. Pomogło w moim przypadku.Po prostu graj z zastępowaniem procesów.
grep
są dwoma plikami binarnymi, które mają takie same dane wyjściowemycommand_exec
jak dane wejściowe specyficzne dla procesu.źródło
Jeśli używasz
zsh
, możesz skorzystać z możliwościMULTIOS
funkcji, tzn.tee
Całkowicie pozbyć się poleceń:zapisze dane wyjściowe z
uname
dwóch różnych plików:file1
ifile2
, co jest równoważneuname | tee file1 >file2
Podobnie przekierowanie standardowych wejść
jest równoważne
cat file1 file2 | wc -l
(należy pamiętać, że nie jest to to samowc -l file1 file2
, co później, zlicza osobno liczbę linii w każdym pliku).Oczywiście można również użyć
MULTIOS
do przekierowania danych wyjściowych nie do plików, ale do innych procesów, stosując podstawianie procesów, np .:źródło
MULTIOS
jest opcją domyślnie WŁĄCZONĄ (i można ją wyłączyć za pomocąunsetopt MULTIOS
).W przypadku stosunkowo niewielkich danych wyjściowych wygenerowanych przez polecenie możemy przekierować dane wyjściowe do pliku tymczasowego i przesłać ten plik tymczasowy do poleceń w pętli. Może to być przydatne, gdy kolejność wykonywanych poleceń może mieć znaczenie.
Na przykład mógłby to zrobić następujący skrypt:
Test działa na Ubuntu 16.04 z
/bin/sh
jakdash
skorupy:źródło
Przechwytuj polecenie
STDOUT
do zmiennej i ponownie używaj jej tyle razy, ile chcesz:Jeśli też chcesz przechwycić
STDERR
, użyj2>&1
na końcu polecenia, tak jak:źródło
Może się to przydać : http://www.spinellis.gr/sw/dgsh/ (ukierunkowana powłoka graficzna) Wydaje się, że zastąpienie basha obsługuje łatwiejszą składnię poleceń „multipipe”.
źródło
Oto szybkie i brudne rozwiązanie częściowe, kompatybilne z dowolną powłoką, w tym
busybox
.Węższy problem, który rozwiązuje to: wydrukuj cały zestaw
stdout
na jednej konsoli i przefiltruj na innym, bez plików tymczasowych lub nazwanych potoków.tty
. Załóżmy/dev/pty/2
.the_program | tee /dev/pty/2 | grep ImportantLog:
Otrzymasz jeden kompletny dziennik i jeden filtrowany.
źródło