Erstellen einer temporären Datei aus der Standardeingabe

Erstellen einer temporären Datei aus der Standardeingabe

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 magicaussehen ?zshbash

Am liebsten hätte ich es so

cat mouse.jpg | submagic | xargs imageviewer

das heißt, ich möchte submagiceine temporäre Datei aus dem Standardeingabestream erstellen und den Dateinamen der erstellten Datei ausgeben.

Die Zeilen magicsollten submagicShell-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 magicoder submagicso, 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 mittmpfile = $(mktemp); cat mouse.jpg | …
  • Umschreiben alsimageviewer =(cat mouse.jpg)
  • Umschreiben alsecho mouse.jpg | xargs imageviewer
  • Verwenden Sie eine Funktion oder eine Binärdatei, um das Problem zu lösen, beispielsweise durch die Definitionfunction 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 imageviewerso hin, als ob es so wäre fehoder sxivso.

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 bashmit der Verwendung einesProzesssubstitution:

utility <( some_other_utility )

Dies würde utilitymit einemDateiname. Wenn utilitydie 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.jpgan 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.jpgto imageviewerkann 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 xargsmit 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 submagicin der Frage habe ich die Antwort bearbeitet.

In zshkö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.jpgist 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 dieTMPSUFFIXspezielle 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 submagicden 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 .$TMPFILEimageviewer

Wenn Sie nach dem Ausführen ein zweites Skript ausführen können, imageviewerkö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

verwandte Informationen