Twoje magiczne połączenie to średnik ... i nawiasy klamrowe:
{ cat wordlist.txt ; ls ~/folder/* ; } | wc -l
Nawiasy klamrowe grupują tylko polecenia, dzięki czemu znak potoku |wpływa na łączny wynik.
Możesz także użyć nawiasów ()wokół grupy poleceń, które wykonałyby polecenia w podpowłoce. Jest to subtelny zestaw różnic z nawiasami klamrowymi, np. Wypróbuj następujące czynności:
cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd
Zobaczysz, że wszystkie zmienne środowiskowe, w tym bieżący katalog roboczy, są resetowane po wyjściu z grupy nawiasów, ale nie po wyjściu z grupy nawiasów klamrowych.
Jeśli chodzi o średnik, alternatywami są znaki &&i ||, które warunkowo wykonają drugie polecenie tylko wtedy, gdy pierwsze zakończy się powodzeniem lub jeśli nie, np.
cd $HOME/project && make
ls $HOME/project || echo "Directory not found."
To działa! Pomóż mi się nauczyć - co dokładnie robią tutaj nawiasy klamrowe? Jakie inne magiczne moce mają?
David Oneill,
@DavidOneill { list; }to polecenie złożone . Od bash(1): lista jest po prostu wykonywana w bieżącym środowisku powłoki. lista musi być zakończona znakiem nowej linii lub średnikiem. [..] Status powrotu to status wyjścia z listy.
Lekensteyn,
Dodałem nieco więcej informacji do odpowiedzi. Ostatecznym przewodnikiem po skryptach powłoki za pomocą bash jest strona podręcznika bash, wpisz man bashz linii poleceń i przejrzyj ją.
pablomme
powinien; w tych poleceniach nie jest && w przypadku, gdy plik wordlist.txt nie istnieje?
Rinzwind
Jeśli wordlist.txtnie istnieje, błąd catpojawi się na standardowym błędzie, ale nie na standardowym wyjściu, więc wc -lnie będzie zliczał żadnych wierszy z niego. To samo dotyczy ~/foldernieistnienia. Można dodać 2> /dev/nullmiędzy każdą z tych komend a ich średnikiem, aby zapobiec zakłóceniom przy standardowym błędzie, ale poza brzydkimi komunikatami o błędach są nieszkodliwe dla zliczania linii.
pablomme
8
Ponieważ wcakceptuje ścieżkę pliku jako dane wejściowe, możesz również użyć podstawienia procesu:
Pamiętaj, że ls ~/folder/*zwraca również zawartość podkatalogów, jeśli takie istnieją (z powodu globalnej ekspansji). Jeśli chcesz tylko wyświetlić zawartość ~/folder, po prostu użyj ls ~/folder.
To wc -lbył tylko wymyślony przykład, w rzeczywistości instaluję go w coś bardziej skomplikowanego, który nie ma tej opcji.
David Oneill,
2
@DavidOneill Cóż, ponieważ catakceptuje argument pliku, możesz użyć, cat <(cat wordlist.txt; ls wordlist.txt) | wc -la nawet cat wordlist.txt <(ls wordlist.txt) | wc -l. Jest to oczywiście bardzo brzydkie, ale pokazuje nieskończone możliwości dzięki narzędziom wiersza poleceń.
Lekensteyn,
1
@DavidOneill Prawidłowo, poprawiłem to teraz, dzięki.
Lekensteyn,
1
Chcesz ls ~/folder/, aby if ~/folderbył dowiązaniem symbolicznym lswyświetla zawartość jego celu zamiast samego łącza. Nawiasem mówiąc, po wszystkich lspoleceniach powinno następować -1tak, aby drukowany był jeden plik na linię i wc -lbył to prawidłowy sposób zliczania plików.
pablomme
@pablomme Masz rację co do dowiązania symbolicznego, ale -1sugeruje się, że wyjście nie jest terminalem, ale potokiem.
Lekensteyn,
2
Zadawałem sobie to samo pytanie i ostatecznie napisałem krótki scenariusz.
magicalUnionThing(Nazywam to append):
#!/bin/sh
cat /dev/stdin
$*
Spraw, aby ten skrypt był wykonywalny
chmod +x ./magicalUnionThing
Teraz ty
cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l
Co to robi:
Wyślij standardowe wejście na standardowe wyjście
Wykonaj argument. $*zwraca wszystkie argumenty jako ciąg. Wyjście tej komendy domyślnie przechodzi na standardowe wyjście skryptu.
Stdout magicalUnionThing będzie więc stdin + stdout polecenia przekazanego jako argument.
Istnieją oczywiście prostsze sposoby, jak w przypadku innych odpowiedzi.
Być może ta alternatywa może być przydatna w niektórych przypadkach.
{ list; }
to polecenie złożone . Odbash(1)
: lista jest po prostu wykonywana w bieżącym środowisku powłoki. lista musi być zakończona znakiem nowej linii lub średnikiem. [..] Status powrotu to status wyjścia z listy.man bash
z linii poleceń i przejrzyj ją.wordlist.txt
nie istnieje, błądcat
pojawi się na standardowym błędzie, ale nie na standardowym wyjściu, więcwc -l
nie będzie zliczał żadnych wierszy z niego. To samo dotyczy~/folder
nieistnienia. Można dodać2> /dev/null
między każdą z tych komend a ich średnikiem, aby zapobiec zakłóceniom przy standardowym błędzie, ale poza brzydkimi komunikatami o błędach są nieszkodliwe dla zliczania linii.Ponieważ
wc
akceptuje ścieżkę pliku jako dane wejściowe, możesz również użyć podstawienia procesu:Odpowiada to mniej więcej:
Pamiętaj, że
ls ~/folder/*
zwraca również zawartość podkatalogów, jeśli takie istnieją (z powodu globalnej ekspansji). Jeśli chcesz tylko wyświetlić zawartość~/folder
, po prostu użyjls ~/folder
.źródło
wc -l
był tylko wymyślony przykład, w rzeczywistości instaluję go w coś bardziej skomplikowanego, który nie ma tej opcji.cat
akceptuje argument pliku, możesz użyć,cat <(cat wordlist.txt; ls wordlist.txt) | wc -l
a nawetcat wordlist.txt <(ls wordlist.txt) | wc -l
. Jest to oczywiście bardzo brzydkie, ale pokazuje nieskończone możliwości dzięki narzędziom wiersza poleceń.ls ~/folder/
, aby if~/folder
był dowiązaniem symbolicznymls
wyświetla zawartość jego celu zamiast samego łącza. Nawiasem mówiąc, po wszystkichls
poleceniach powinno następować-1
tak, aby drukowany był jeden plik na linię iwc -l
był to prawidłowy sposób zliczania plików.-1
sugeruje się, że wyjście nie jest terminalem, ale potokiem.Zadawałem sobie to samo pytanie i ostatecznie napisałem krótki scenariusz.
magicalUnionThing
(Nazywam toappend
):Spraw, aby ten skrypt był wykonywalny
Teraz ty
Co to robi:
$*
zwraca wszystkie argumenty jako ciąg. Wyjście tej komendy domyślnie przechodzi na standardowe wyjście skryptu.Stdout magicalUnionThing będzie więc stdin + stdout polecenia przekazanego jako argument.
Istnieją oczywiście prostsze sposoby, jak w przypadku innych odpowiedzi.
Być może ta alternatywa może być przydatna w niektórych przypadkach.
źródło