從標準輸入建立臨時文件

從標準輸入建立臨時文件

假設我有一個標準輸入流文件內容和一個期望的命令檔案名稱作為參數,我想在由標準輸入流的文件內容組成的文件上運行該命令。

例如,代替命令

imageviewer mouse.jpg

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

cat mouse.jpg | magic

這在ormagic中會是什麼樣子呢?zshbash

最好,我希望它看起來像

cat mouse.jpg | submagic | xargs imageviewer

也就是說,我想submagic從標準輸入流建立一個臨時檔案並輸出建立的檔案的檔案名稱。

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


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


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

imageviewer mouse.jpg

正好開始cat mouse.jpg | …。也就是說,我真的確切地一條線magicsubmagic類似的確切地上面的管道工作——我的意思是字面意思。

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

  • 開始管道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 提供標記附加文件,然後將文件內容透過管道傳輸到您可以輸入的命令列。這就是問題的來源。但我對原來的問題不感興趣,只對這個問題感興趣。

答案1

至少bash,使用流程替代

utility <( some_other_utility )

這將呈現utility一個檔案名稱。當utility打開文件並從中讀取時,它將讀取some_other_utility.


你的例子:

cat mouse.jpg | submagic | xargs imageviewer

我假設這是為了發送檔案名稱 mouse.jpgimageviewer,因為透過 發送 JPEG 檔案的內容沒有意義xargs

這可以透過以下方式完成

echo 'mouse.jpg' | xargs imageviewer

或者

xargs imageviewer <<<'mouse.jpg'

bash

mouse.jpg發送to的內容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直到它從管道的中間部分讀取檔案名稱。在建立臨時檔案之前,中間命令不會輸出檔案名稱。

答案2

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

zsh可以從命令的輸出建立一個臨時檔案=( ... )。與<( ... )可能使用裝置檔案(如/dev/fd...命名管道)相反,該表單=( ... )會建立可尋找的臨時檔案。看http://zsh.sourceforge.net/Doc/Release/Expansion.html#Process-Substitution

假設這cat mouse.jpg只是將圖像資料傳送到 stdout 的任何命令的範例,您可以使用

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 )不會刪除。$TMPFILEimageviewer

如果您可以在運行後運行第二個腳本,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

答案3

為了滿足您的問題的確切要求,您可以執行以下操作:

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

相關內容