Bash

從標準輸入創建臨時文件

  • January 26, 2019

假設我有一個文件內容的標準輸入流和一個需要文件名作為參數的命令,並且我想在由標準輸入流的文件內容組成的文件上執行該命令。

例如,而不是命令

imageviewer mouse.jpg

我想要一些神奇的線條magic,使它相當於

cat mouse.jpg | magic

這在ormagic中會是什麼樣子?zsh``bash

最好是,我希望它看起來像

cat mouse.jpg | submagic | xargs imageviewer

也就是說,我想submagic從標準輸入流創建一個臨時文件並輸出創建的文件的文件名。

這些行magicsubmagic應該是僅使用 bash 或 zsh 命令、它們的內置命令、GNU coreutils 等的 shell 管道。


這是整個問題。以下只是澄清和背景,因為人們一直誤解我的意思。


好的,所以我以為我說清楚了,但似乎我沒有說清楚:我真的希望有一個管道相當於

imageviewer mouse.jpg

正是從 .開始cat mouse.jpg | …。也就是說,我真的想要一條線或這樣一條線,這樣上面的管道就可以正常工作——我的意思是我的問題。magic``submagic

這尤其意味著以下建議的解決方案不起作用:

  • 開始管道tmpfile = $(mktemp); cat mouse.jpg | …
  • 將其重寫為imageviewer =(cat mouse.jpg)
  • 將其重寫為echo mouse.jpg | xargs imageviewer
  • 使用函式或二進製文件來解決它,比如通過定義function magic () { … }

可以說,我感興趣的是是否可以編寫別名alias magic='…',或者是否可以編寫alias submagic='…'上述管道之一,並且這些別名的定義僅包含 bash 或 zsh 命令、GNU coreutils 等 -沒有什麼自己寫的。

另一個評論。你認為imageviewerfehsxiv或某事。

背景。當我嘗試使用我的郵件客戶端打開幾個附加到郵件的圖像文件時,我想到了這個問題neomutt。Neomutt 提供標記附加文件,然後將文件內容通過管道傳輸到您可以輸入的命令行。所以在這裡,我只能給出一個命令行,它在給定的標準輸入流上執行某些操作。這就是問題的來源。但我對原始問題不感興趣,而只對這個問題感興趣。

bash至少,使用過程替換

utility <( some_other_utility )

這將顯示utility一個文件名。當utility打開文件並從中讀取時,它將讀取some_other_utility.


你的例子:

cat mouse.jpg | submagic | xargs imageviewer

我假設這是為了將文件名 mouse.jpg發送到imageviewer,因為通過xargs.

這可以通過

echo 'mouse.jpg' | xargs imageviewer

或者

xargs imageviewer <<<'mouse.jpg'

bash.

發送 to 的內容mouse.jpg可以imageviewer

cat mouse.jpg | imageviewer /dev/stdin

或者,使用過程替換,與

imageviewer <( cat mouse.jpg )

使用臨時文件:

tmpfile=$(mktemp)
cat mouse.jpg >"$tmpfile"

imageviewer "$tmpfile"

rm "$tmpfile"

可能,

tmpfile=$(mktemp)
cat mouse.jpg | { cat >"$tmpfile"; echo "$tmpfile"; } | xargs imageviewer
rm "$tmpfile"

xargs該管道依賴於等待執行的事實,imageviewer直到它從管道的中間部分讀取文件名。在創建臨時文件之前,中間命令不會輸出文件名。

在澄清submagic問題後,我編輯了答案。

zsh您可以使用命令的輸出創建一個臨時文件=( ... )。與之相反<( ... ),可以使用設備文件/dev/fd...或命名管道,表單=( ... )創建可查找的臨時文件。請參閱http://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution

假設這cat mouse.jpg只是將圖像數據發送到標準輸出的任何命令的範例,您可以使用

imageviewer =(cat mouse.jpg)

如果您需要 zsh 創建的臨時文件具有特定的副檔名,您可以設置TMPSUFFIX特殊變數):

(TMPSUFFIX=.jpg; imageviewer =(cat mouse.jpg))

第二次更新

如果你堅持語法

cat mouse.jpg | submagic | xargs imageviewer

可以創建一個submagic類似於 Kusalananda 回答中已經提出的命令的腳本。

#! /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"

與這樣的 shell 機制相反,執行後=( cat mouse.jpg )不會刪除。$TMPFILE``imageviewer

如果您可以在執行後執行第二個腳本,imageviewer如果它知道名稱,則可以刪除該文件。

腳本submagic-cleanup

#! /bin/sh

# A fixed name allows a simple script for cleaning up.
TMPFILE=/tmp/submagic.tmp.jpg
rm -f "$TMPFILE"

然後你可以執行

cat mouse.jpg | submagic | xargs imageviewer
submagic-cleanup

引用自:https://unix.stackexchange.com/questions/495254