
Angenommen, ich habe einen Standardeingabestream vonDateiinhaltund ein Befehl, der eineDateinameals Argument und ich möchte diesen Befehl für eine Datei ausführen, die aus dem Dateiinhalt des Standardeingabestreams besteht.
Beispielsweise statt des Befehls
imageviewer mouse.jpg
Ich möchte eine magische Linie magic
, die dies gleichbedeutend macht mit
cat mouse.jpg | magic
Wie würde das in oder magic
aussehen ?zsh
bash
Am liebsten hätte ich es so
cat mouse.jpg | submagic | xargs imageviewer
das heißt, ich möchte submagic
eine temporäre Datei aus dem Standardeingabestream erstellen und den Dateinamen der erstellten Datei ausgeben.
Die Zeilen magic
sollten submagic
Shell-Pipelines sein, die nur Bash- oder Zsh-Befehle, deren integrierte Funktionen, GNU-Coreutils und Ähnliches verwenden.
Dies ist die gesamte Frage. Nachfolgend finden Sie lediglich Erläuterungen und Hintergrundinformationen, da die Leute immer wieder missverstanden haben, was ich meinte.
Okay, ich dachte, ich hätte es klar ausgedrückt, aber anscheinend war das nicht der Fall: IchWirklichwollen eine Pipeline haben, die das Äquivalent von
imageviewer mouse.jpg
Dasbeginnt genaumit cat mouse.jpg | …
. Das heißt, ichWirklichwollengenaueine Linie magic
oder submagic
so, dassgenaudie oben genannten Pipelines funktionieren – ich habe meine Frage wörtlich gemeint.
Dies bedeutet insbesondere, dass folgende Lösungsvorschläge nicht infrage kommen:
- Beginn der Pipeline mit
tmpfile = $(mktemp); cat mouse.jpg | …
- Umschreiben als
imageviewer =(cat mouse.jpg)
- Umschreiben als
echo mouse.jpg | xargs imageviewer
- Verwenden Sie eine Funktion oder eine Binärdatei, um das Problem zu lösen, beispielsweise durch die Definition
function magic () { … }
Man kann sagen, dass mich interessiert, ob es möglich ist, einen Alias alias magic='…'
oder alias submagic='…'
so zu schreiben, dass eine der oben genannten Pipelines funktioniert und dass die Definition dieser Aliase nichts weiter enthält als Bash- oder Zsh-Befehle, GNU-Coreutils und dergleichen – nichts Selbstgeschriebenes.
Ein weiterer Kommentar. Du nimmst es imageviewer
so hin, als ob es so wäre feh
oder sxiv
so.
Hintergrund. Diese Frage kam mir, als ich versuchte, mit meinem Mail-Client mehrere an eine Mail angehängte Bilddateien zu öffnen neomutt
. Neomutt bietet an, angehängte Dateien zu markieren und den Dateiinhalt dann an eine Kommandozeile weiterzuleiten, die man eingeben kann. Daher kann ich hier nur eine Kommandozeile angeben, die etwas auf einem gegebenen Standardeingabestream ausführt. Daher stammt die Frage. Aber mich interessiert nicht das ursprüngliche Problem, sondern nur diese Frage.
Antwort1
Zumindest bash
mit der Verwendung einesProzesssubstitution:
utility <( some_other_utility )
Dies würde utility
mit einemDateiname. Wenn utility
die Datei geöffnet und daraus gelesen wird, wird die Standardausgabe von gelesen some_other_utility
.
Ihr Beispiel:
cat mouse.jpg | submagic | xargs imageviewer
Ich nehme an, dass dies dazu gedacht ist, dieDateiname mouse.jpg
an imageviewer
, da es keinen Sinn ergibt, den Inhalt einer JPEG-Datei über zu senden xargs
.
Dies könnte erreicht werden durch
echo 'mouse.jpg' | xargs imageviewer
oder
xargs imageviewer <<<'mouse.jpg'
In bash
.
Das Senden des Inhalts von mouse.jpg
to imageviewer
kann erfolgen mit
cat mouse.jpg | imageviewer /dev/stdin
oder, unter Verwendung der Prozesssubstitution, mit
imageviewer <( cat mouse.jpg )
Verwenden einer temporären Datei:
tmpfile=$(mktemp)
cat mouse.jpg >"$tmpfile"
imageviewer "$tmpfile"
rm "$tmpfile"
Möglicherweise,
tmpfile=$(mktemp)
cat mouse.jpg | { cat >"$tmpfile"; echo "$tmpfile"; } | xargs imageviewer
rm "$tmpfile"
Diese Pipeline basiert darauf, dass xargs
mit der Ausführung gewartet wird imageviewer
, bis der Dateiname aus dem mittleren Teil der Pipeline gelesen wurde. Der Dateiname wird vom mittleren Befehl erst ausgegeben, wenn die temporäre Datei erstellt wurde.
Antwort2
Nach einer Klarstellung submagic
in der Frage habe ich die Antwort bearbeitet.
In zsh
können Sie aus der Ausgabe eines Befehls mit eine temporäre Datei erstellen =( ... )
. Im Gegensatz zu , <( ... )
bei dem Sie eine Gerätedatei wie /dev/fd...
oder eine benannte Pipe verwenden können, erstellt das Formular =( ... )
eine suchbare temporäre Datei. Siehehttp://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution
Angenommen, dies cat mouse.jpg
ist nur ein Beispiel für jeden Befehl, der Bilddaten an stdout sendet, können Sie verwenden
imageviewer =(cat mouse.jpg)
Wenn Sie möchten, dass die von zsh erstellte temporäre Datei eine bestimmte Erweiterung hat, können Sie dieTMPSUFFIX
spezielle Variable):
(TMPSUFFIX=.jpg; imageviewer =(cat mouse.jpg))
zweites Update
Wenn Sie auf der Syntax bestehen
cat mouse.jpg | submagic | xargs imageviewer
es wäre möglich, ein Skript zu erstellen, das submagic
den Befehlen ähnelt, die bereits in Kusalanandas Antwort vorgeschlagen wurden.
#! /bin/sh
# A fixed name allows multiple runs without creating lots of files and
# allows a simple script to remove the file afterwards.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE" && cat > "$TMPFILE" && echo "$TMPFILE"
Im Gegensatz zu Shell-Mechanismen wie diesem würde dieser nach dem Ausführen =( cat mouse.jpg )
nicht entfernt .$TMPFILE
imageviewer
Wenn Sie nach dem Ausführen ein zweites Skript ausführen können, imageviewer
könnte dieses die Datei entfernen, sofern es den Namen kennt.
Skriptsubmagic-cleanup
#! /bin/sh
# A fixed name allows a simple script for cleaning up.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE"
Dann könntest du rennen
cat mouse.jpg | submagic | xargs imageviewer
submagic-cleanup
Antwort3
Um die genauen Anforderungen Ihrer Frage zu erfüllen, können Sie Folgendes tun:
cat mouse.jpg | { tf=$(mktemp); cat >"$tf"; echo "$tf"; } | xargs imageviewer