
假設我有一個標準輸入流文件內容和一個期望的命令檔案名稱作為參數,我想在由標準輸入流的文件內容組成的文件上運行該命令。
例如,代替命令
imageviewer mouse.jpg
我想要一些神奇的線條magic
,使它相當於
cat mouse.jpg | magic
這在ormagic
中會是什麼樣子呢?zsh
bash
最好,我希望它看起來像
cat mouse.jpg | submagic | xargs imageviewer
也就是說,我想submagic
從標準輸入流建立一個臨時檔案並輸出建立的檔案的檔案名稱。
這些行magic
或submagic
應該是僅使用 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 等 -沒有什麼是自己寫的。
另一則評論。你認為imageviewer
是feh
或sxiv
某事。
背景。當我嘗試使用我的郵件用戶端開啟郵件中附加的多個映像檔時,我想到了這個問題neomutt
。 Neomutt 提供標記附加文件,然後將文件內容透過管道傳輸到您可以輸入的命令列。這就是問題的來源。但我對原來的問題不感興趣,只對這個問題感興趣。
答案1
至少bash
,使用流程替代:
utility <( some_other_utility )
這將呈現utility
一個檔案名稱。當utility
打開文件並從中讀取時,它將讀取some_other_utility
.
你的例子:
cat mouse.jpg | submagic | xargs imageviewer
我假設這是為了發送檔案名稱 mouse.jpg
到imageviewer
,因為透過 發送 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 )
不會刪除。$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
答案3
為了滿足您的問題的確切要求,您可以執行以下操作:
cat mouse.jpg | { tf=$(mktemp); cat >"$tf"; echo "$tf"; } | xargs imageviewer