Ihre magische Vereinigungssache ist ein Semikolon ... und geschweifte Klammern:
{ cat wordlist.txt ; ls ~/folder/* ; } | wc -l
Die geschweiften Klammern gruppieren nur die Befehle, sodass sich das Pipe-Zeichen |auf die kombinierte Ausgabe auswirkt.
Sie können auch Klammern ()um eine Befehlsgruppe verwenden, um die Befehle in einer Subshell auszuführen. Dies hat eine subtile Reihe von Unterschieden mit geschweiften Klammern, z. B. probieren Sie Folgendes aus:
cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd
Sie werden feststellen, dass alle Umgebungsvariablen, einschließlich des aktuellen Arbeitsverzeichnisses, nach dem Verlassen der Gruppe in Klammern zurückgesetzt werden, jedoch nicht nach dem Verlassen der Gruppe in geschweiften Klammern.
Was das Semikolon betrifft, enthalten Alternativen die Zeichen &&und ||, die den zweiten Befehl nur dann bedingt ausführen, wenn der erste erfolgreich ist oder wenn dies nicht der Fall ist, z
cd $HOME/project && make
ls $HOME/project || echo "Directory not found."
Das geht doch! Hilf mir zu lernen - was genau machen die geschweiften Klammern hier? Welche anderen magischen Kräfte haben sie?
David Oneill
@DavidOneill { list; }ist ein zusammengesetzter Befehl . From bash(1): list wird einfach in der aktuellen Shell-Umgebung ausgeführt. Liste muss mit einem Zeilenumbruch oder einem Semikolon abgeschlossen werden. [..] Der Rückgabestatus ist der Exit-Status der Liste.
Lekensteyn
Ich habe ein bisschen mehr Infos zur Antwort hinzugefügt. Die endgültige Anleitung zum Erstellen von Shell-Skripten mit bash ist die bash-Manpage. man bashGeben Sie sie über die Befehlszeile ein und durchsuchen Sie sie.
Pablomme
Sollte die ; in diesen Befehlen nicht && sein, falls die Datei wordlist.txt nicht existiert?
Rinzwind
Wenn wordlist.txtkein Fehler von vorhanden ist, catwird dieser bei Standardfehlern, jedoch nicht bei der Standardausgabe angezeigt, sodass wc -lkeine Zeilen von diesem Fehler gezählt werden . Gleiches gilt für ~/foldernicht vorhandene. Man könnte 2> /dev/nullzwischen jedem dieser Befehle ein Semikolon einfügen, um Rauschen bei Standardfehlern zu vermeiden, aber abgesehen davon, dass sie hässlich sind, sind Fehlermeldungen harmlos, um Zeilen zu zählen.
Pablomme
8
Da wcein Dateipfad als Eingabe akzeptiert wird, können Sie auch die Prozessersetzung verwenden:
Beachten Sie, dass ls ~/folder/*auch der Inhalt von Unterverzeichnissen zurückgegeben wird, falls vorhanden (aufgrund der Glob-Erweiterung). Wenn Sie nur den Inhalt auflisten möchten ~/folder, verwenden Sie einfach ls ~/folder.
Das wc -lwar nur ein erfundenes Beispiel, ich füge es tatsächlich in etwas Komplizierteres ein, das diese Option nicht hat.
David Oneill
2
@DavidOneill Nun, wie catein Datei-Argument akzeptiert, können Sie cat <(cat wordlist.txt; ls wordlist.txt) | wc -lund sogar verwenden cat wordlist.txt <(ls wordlist.txt) | wc -l. Das ist natürlich sehr hässlich, zeigt aber die unendlichen Möglichkeiten mit Kommandozeilen-Tools.
Lekensteyn
1
@DavidOneill Richtig, ich habe es jetzt korrigiert, danke.
Lekensteyn
1
Du willst ls ~/folder/also das wenn~/folder ein symbolischer Link lsden Inhalt seines Ziels anstelle des Links selbst auflistet. Übrigens sollten alle lsBefehle befolgt werden, -1damit eine einzelne Datei pro Zeile gedruckt wird und wc -leine gültige Methode zum Zählen von Dateien ist.
Pablomme
@pablomme In Bezug auf das Symlink-Ding sind Sie der Meinung, aber dies -1impliziert, dass die Ausgabe kein Terminal, sondern eine Pipe ist.
Lekensteyn,
2
Ich stellte mir die gleiche Frage und schrieb schließlich ein kurzes Drehbuch.
magicalUnionThing(Ich nenne es append):
#!/bin/sh
cat /dev/stdin
$*
Mach das Skript ausführbar
chmod +x ./magicalUnionThing
Jetzt machst du
cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l
Was es macht:
Standardeingabe an Standardausgabe senden
Argument ausführen. $*Gibt alle Argumente als String zurück. Die Ausgabe dieses Befehls erfolgt standardmäßig in der Skript-Standardausgabe.
Die Standardausgabe von magicalUnionThing ist also die Standardausgabe + Standardausgabe des Befehls, der als Argument übergeben wird.
Es gibt natürlich einfachere Wege, als nach anderen Antworten.
Vielleicht kann diese Alternative in einigen Fällen nützlich sein.
{ list; }
ist ein zusammengesetzter Befehl . Frombash(1)
: list wird einfach in der aktuellen Shell-Umgebung ausgeführt. Liste muss mit einem Zeilenumbruch oder einem Semikolon abgeschlossen werden. [..] Der Rückgabestatus ist der Exit-Status der Liste.man bash
Geben Sie sie über die Befehlszeile ein und durchsuchen Sie sie.wordlist.txt
kein Fehler von vorhanden ist,cat
wird dieser bei Standardfehlern, jedoch nicht bei der Standardausgabe angezeigt, sodasswc -l
keine Zeilen von diesem Fehler gezählt werden . Gleiches gilt für~/folder
nicht vorhandene. Man könnte2> /dev/null
zwischen jedem dieser Befehle ein Semikolon einfügen, um Rauschen bei Standardfehlern zu vermeiden, aber abgesehen davon, dass sie hässlich sind, sind Fehlermeldungen harmlos, um Zeilen zu zählen.Da
wc
ein Dateipfad als Eingabe akzeptiert wird, können Sie auch die Prozessersetzung verwenden:Dies entspricht in etwa:
Beachten Sie, dass
ls ~/folder/*
auch der Inhalt von Unterverzeichnissen zurückgegeben wird, falls vorhanden (aufgrund der Glob-Erweiterung). Wenn Sie nur den Inhalt auflisten möchten~/folder
, verwenden Sie einfachls ~/folder
.quelle
wc -l
war nur ein erfundenes Beispiel, ich füge es tatsächlich in etwas Komplizierteres ein, das diese Option nicht hat.cat
ein Datei-Argument akzeptiert, können Siecat <(cat wordlist.txt; ls wordlist.txt) | wc -l
und sogar verwendencat wordlist.txt <(ls wordlist.txt) | wc -l
. Das ist natürlich sehr hässlich, zeigt aber die unendlichen Möglichkeiten mit Kommandozeilen-Tools.ls ~/folder/
also das wenn~/folder
ein symbolischer Linkls
den Inhalt seines Ziels anstelle des Links selbst auflistet. Übrigens sollten allels
Befehle befolgt werden,-1
damit eine einzelne Datei pro Zeile gedruckt wird undwc -l
eine gültige Methode zum Zählen von Dateien ist.-1
impliziert, dass die Ausgabe kein Terminal, sondern eine Pipe ist.Ich stellte mir die gleiche Frage und schrieb schließlich ein kurzes Drehbuch.
magicalUnionThing
(Ich nenne esappend
):Mach das Skript ausführbar
Jetzt machst du
Was es macht:
$*
Gibt alle Argumente als String zurück. Die Ausgabe dieses Befehls erfolgt standardmäßig in der Skript-Standardausgabe.Die Standardausgabe von magicalUnionThing ist also die Standardausgabe + Standardausgabe des Befehls, der als Argument übergeben wird.
Es gibt natürlich einfachere Wege, als nach anderen Antworten.
Vielleicht kann diese Alternative in einigen Fällen nützlich sein.
quelle