Frage Wie füge ich Ergebnisse von zwei verschiedenen Befehlen zu einem Befehl zusammen?


Ich möchte merge (Union) Ausgabe von zwei verschiedenen Befehlen und Pipe sie zu einem einzigen Befehl.

Ein dummes Beispiel:

Befehle Ich möchte die Ausgabe zusammenführen:

cat wordlist.txt
ls ~/folder/*

in:

wc -l

In diesem Beispiel, wenn wordlist.txt 5 Zeilen und 3 Dateien enthält, möchte ich wc -l zurückgeben

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

Wie mache ich das?


28
2018-05-07 19:05


Ursprung




Antworten:


Ihre magische Gewerkschaftssache ist ein Semikolon ... und geschweifte Klammern:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

Die Klammern gruppieren nur die Befehle zusammen, so dass das Pipe-Zeichen | beeinflusst die kombinierte Ausgabe.

Sie können auch Klammern verwenden () um eine Befehlsgruppe, die die Befehle in einer Subshell ausführen würde. Dies hat einen subtilen Satz von Unterschieden mit geschweiften Klammern, z. versuche folgendes:

    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 Beenden der Klammergruppe zurückgesetzt werden, jedoch nicht nach dem Beenden der geschweiften Klammergruppe.

Was das Semikolon anbelangt, sind Alternativen die && und || Zeichen, die den zweiten Befehl nur dann bedingt ausführen, wenn der erste erfolgreich ist oder wenn nicht, z.

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."

43
2018-05-07 19:09



Das funktioniert! 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. Von bash(1): Liste wird einfach in der aktuellen Shell-Umgebung ausgeführt. Liste muss mit einem Newline oder Semikolon beendet werden. [..] Der Rückgabestatus ist der Exit-Status der Liste. - Lekensteyn
Ich habe ein bisschen mehr Informationen zu der Antwort hinzugefügt. Die definitive Anleitung zum Shell-Scripting mit bash ist die Bash-Manpage type man bash von der Befehlszeile und durchsuchen Sie es. - pablomme
Sollte die ; in diesen Befehlen nicht && sein, falls die Datei wordlist.txt nicht existiert? - Rinzwind
Ob wordlist.txt Es existiert kein Fehler von cat erscheint auf Standardfehler, aber nicht auf Standardausgabe, also wc -l zählt keine Zeilen daraus. Gleiches gilt für ~/folder nicht existierend. Man könnte hinzufügen 2> /dev/nullzwischen jedem dieser Befehle und ihrem Semikolon, um Rauschen bei Standardfehlern zu vermeiden, aber abgesehen davon, dass sie hässlich sind, sind Fehlermeldungen zum Zweck des Zählens von Zeilen harmlos. - pablomme


Schon seit wc akzeptiert einen Dateipfad als Eingabe, Sie können auch Prozesssubstitution verwenden:

wc -l <(cat wordlist.txt; ls ~/folder/*)

Dies entspricht in etwa:

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

Beachten Sie, dass ls ~/folder/* gibt auch den Inhalt von Unterverzeichnissen zurück, falls vorhanden (aufgrund der Glob-Erweiterung). Wenn Sie nur den Inhalt von ~/folder, benutz einfach ls ~/folder.


8
2018-05-07 19:10



Das wc -l war nur ein erfundenes Beispiel, ich bin es in etwas komplizierter, die diese Option nicht hat. - David Oneill
@DavidOneill Nun, als cat akzeptiert ein Dateiargument, das Sie verwenden können cat <(cat wordlist.txt; ls wordlist.txt) | wc -l und selbst cat wordlist.txt <(ls wordlist.txt) | wc -l. Das ist natürlich sehr hässlich, aber es zeigt die endlosen Möglichkeiten mit Kommandozeilen-Tools. - Lekensteyn
Ah, ich verstehe was du meinst. Vielen Dank! - David Oneill
@DavidOneill Richtig, ich habe es jetzt korrigiert, danke. - Lekensteyn
Sie wollen ls ~/folder/ so dass wenn ~/folder ist ein symbolischer Link ls listet den Inhalt seines Ziels anstelle des Links selbst auf. Übrigens, all das ls Befehle sollten gefolgt werden von -1 so dass eine einzelne Datei pro Zeile gedruckt wird und wc -l ist eine gültige Methode zum Zählen von Dateien. - pablomme


Ich stellte mir die gleiche Frage und schrieb ein kurzes Drehbuch.

magicalUnionThing (I nenne es append):

#!/bin/sh
cat /dev/stdin
$*

Machen Sie das Skript ausführbar

chmod +x ./magicalUnionThing

Jetzt machst du

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

Was es macht:

  • Senden Sie die Standardeingabe an die Standardausgabe
  • Argument ausführen $* gibt alle Argumente als String zurück. Die Ausgabe dieses Befehls wird standardmäßig in die Skriptstandardausgabe übernommen.

Das stdout von magicUnionThing ist also stdin + stdout des Befehls, der als Argument übergeben wird.

Es gibt natürlich einfachere Wege, wie bei anderen Antworten.
Vielleicht kann diese Alternative in einigen Fällen nützlich sein.


1
2018-03-11 11:17