Jestem nowy w bash i nie mogę przez całe życie wymyślić, jak uruchomić określone polecenie, przypuszczać ./fff
i drukować standardowe stdouts przed stderr (sam jestem zdezorientowany co do znaczenia)
na przykład
$ printf "I am a\ndrill\n" > fff;
$ cat fff nofile fff nofile fff
I am a
drill
cat: nofile: No such file or directory
I am a
drill
cat: nofile: No such file or directory
I am a
drill
musi drukować jak:
I am a
drill
I am a
drill
I am a
drill
cat: nofile: No such file or directory
cat: nofile: No such file or directory
Rozumiem, że najpierw muszę przekierować dane wyjściowe do pliku, a następnie dołączyć błąd do tego samego pliku, jednak takie dane wyjściowe otrzymuję
$ cat ./foo nofile ./foo nofile ./foo <<< $(touch fin) > see 2>> see
I am a
drill
I am a
drill
I am a
drill
ectory
cat: nofile: No such file or directory
cat
naprawdę „a” zastąpiono „niektórymi”?Odpowiedzi:
W każdym razie musisz gdzieś przechowywać wyjście stderr, aby móc wyświetlić go na końcu.
Plik przychodzi do głowy:
Lub pamięć (tutaj przy użyciu
sponge
zmoreutils
):{...} 3>&1
: w obrębie{...}
deskryptora pliku (fd) 3 wskazuje na ten sam zasób, co oryginalny stdout (więc możemy go użyć do przywrócenia standardowego wejściafff
).fff <redirs> | sponge <redirs>
,fff
isponge
zaczął jednocześnie (z<redirs>
zastosowanym niezależnie) ze standardowymfff
wyjściem do potoku, asponge
standardowym wyjściem jest drugi koniec potoku.2>&1
: fd 2 zfff
(stderr) wskazuje na to samo, co na 1: potok w tym punkcie, więcfff
błąd przechodzisponge
przez tę potok.>&3
: teraz stdout wskazuje na pierwotne stdout (przekierowuje z powrotem do tego, co było)3>&-
: zamykamy fd 2, któryfff
nie potrzebujesponge
gromadzi swoje dane wejściowe i wyświetla je tylko (na swoim standardzie, który został przekierowany>&2
do tego samego zasobu co stderr) po wykryciu eof na swoim standardzie (zakłada się, że jest onfff
zakończony i zapisał już wszystkie swoje wyjścia na standardowym standardzie ).Jeśli
sponge
nie jest zainstalowany, możesz go zastąpićperl -0777 -pe ''
. Dzięki-pe ''
,perl
brzmi jeden rekord w czasie od jej wejścia i zapisuje je na standardowe wyjście.-0777
jest trybem slurp, w którym (tylko w tym przypadku) rekord jest całym wejściem.źródło
tee
zamiastsponge
...?tee
nie przechowuje danych, zapisuje je natychmiast po ich odczytaniu.cat foo nofile foo nofile foo 2> ferr.txt; cat ferr.txt
. (I prawdopodobnie nie chcesz używać>>
.) Ponadto Stéphane podkreśla, że powinieneś prawdopodobniecat ferr.txt >&2
napisać informacje o stderr do stderr.