這是我的用例:命令列實用程式可以接受帶有命令列melt
副檔名的檔案名,然後打開它;.melt
例如,這是一個正確的test_p.melt
文件:
colour:blue
out=24
colour:red
out=48
....開啟並播放melt test_p.melt
.
現在,問題是.melt
文件不支援註釋,我希望它們支援註釋(對於包含不可解析參數的任何行,您都會收到錯誤訊息,包括帶有 a 的行#
)。所以這是一個有註解的test_c.melt
文件:
# master comment here
colour:blue # this is blue!
out=24
colour:red
out=48
直接打開它melt
給出:
$ melt test_c.melt
Failed to load "# master comment here"
...
....並且沒有顯示藍色畫面。
所以我想 - 好吧,我可以發表評論反正,然後使用 Bash 進程替換來過濾文件sed
,並將其提供給melt
應用程式。首先嘗試用 進行測試cat
,成功:
$ cat <(sed 's/#.*$//' test_c.melt)
colour:blue
out=24
colour:red
out=48
.... 看起來不錯;但,如果我嘗試使用melt
,它就會識破我的詭計:
$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"
基本上,melt 取得了為進程替換提供的 Bash 管道的檔案名稱 - 但不幸的是,它melt
所做的是argv[i]
直接處理;如果是文件,則需要.melt
在文件名稱中看到副檔名;如果沒有 - 過程失敗。
所以我的問題是:在這種情況下,如何使用進程替換 - 因此管道的檔案名稱具有特定的擴展名.melt
?基本上,作為替換的結果,我想要一個管道文件名/dev/fd/62.melt
,我認為它會通過。
注意:當然,我總是可以這樣做:
sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt
……但首先,這裡有兩個命令 - 我想要一個單行管道;另一方面,它提出了另一個問題,即我考慮之後刪除臨時文件,這是我不喜歡的。
這是否可以透過 Bash 進程替換來實現——或者以某種方式透過標準 Linux 工具來實現?
答案1
一種可能性是指向melt
顯示檔案修改副本的檔案系統。保險絲是建構檔案系統驅動程式的通用方法,由普通程式實現,不需要特權。有許多 FUSE 檔案系統,並且其中之一很有可能可以幫助您。這個想法是提供一個掛載點,讀取.melt
文件時會讀取“真實”文件,但註釋會被過濾掉。
腳本檔案系統看起來很有希望(但我從未使用過它)。像這樣的東西應該有效:
mkdir ~/uncommented-melt
scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt
包含您的文件~/work
的樹的根在哪裡.melt
~/bin/uncomment-melt
#!/bin/sh
sed 's/#.*$//' "$1"
然後,如果您有帶有註釋的文件~/work/test_c.melt
,則可以運行melt ~/uncommented-melt/test_c.melt
.
其他可能有用的 FUSE 檔案系統:
答案2
使用zsh
shell,您可以使用=(...)
進程替換的形式(使用臨時檔案而不是/dev/fd/x
檔案和管道),您可以為其指定後綴:
(TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))
有關詳細信息,請參閱info zsh TMPSUFFIX
(假設info
頁面已安裝,您可能需要安裝軟體包zsh-doc
)。
答案3
好吧,事實證明,在我的具體情況下,這些熔化腳本將被嚴格解釋為命令列參數;所以僅僅sed
OP中的一個並不能完全解決它(另外,還有其他東西,例如可以設定的設定檔)。所以這就是我最終所做的 - 可能可以在 OP 標題所涵蓋的其他情況下提供靈感。
我最終決定使用這個:創建一個test.shmelt
文件,它實際上是一個bash
包含我註釋的melt
腳本程式碼的腳本;使該文件可執行chmod +x test.shmelt
;然後編輯腳本後,將其運行為./test.shmelt
.
運行時,它將test.melt
在 中建立一個「已清理」的文件/tmp
,並呼叫melt
該文件。由於melt
通常在程式結束後在終端機中繼續運行,因此透過 SIGINT 上的陷阱,可以在按下 Ctrl-C 時清除此臨時檔案(但不是必須)。
就這樣,我還是有意見的;可以在來源檔案中快速編輯並運行melt並查看結果;並且還有一個“清理”了評論的文件,供我稍後使用。
這是代碼test.shmelt
:
#!/bin/bash
# call with: ./test.shmelt
#TMLTFILE="test.melt" # for final export
TMLTFILE="${0%%.shmelt}.melt" # for final export
function finished() { echo ; } ; # use this when testing or montaging to keep exported (tmp) .melt file; uncomment the below to remove the tmp file
#~ function finished() { rm /tmp/"$TMLTFILE"; echo "fin1 $0" ; } ; trap finished SIGINT ;
echo 'Remember `pulseaudio --start` to hear audio with `melt`!'
pulseaudio --check
if [ $? -ne 0 ]; then
pulseaudio --start
fi
DIRNAME=$(readlink -f $(dirname $0))
PROFILE="square_ntsc"
echo "
# the profile doesn't work from here;
# still has to be specified on command line
# but including it here so the path is saved for testing
#~ -profile
#~ ${PROFILE}
-video-track
# can avoid pixmap: here, but that s the producer;
# qimage: also works
# NB it is NOT '-out 1645'; but 'out=1645'!!
/media/myimg/%05d.bmp
in=0
out=1645
#~ length=1645
#~ loop=0
#~ eof=stop
-audio-track
/media/mysnd/snd.wav
in=0
out=1645
#~ loop=0
#~ eof=stop
#-consumer xml # doesn't work here
" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e '/^[[:space:]]*$/d' -e 's/[[:blank:]]*$//' > ${TMLTFILE}
# the sed: remove comments; remove indents; remove empty lines; remove spaces at end of line
# eof: one of: stop, loop, continue or pause (eof=stop)
# to loop, use `melt eof=loop ...` (but make sure first,
# that the edit as a whole stops - use xml to check!)
# due to caching issues, preview pieces (up to ~300 frames) like this:
melt eof=loop -profile ${PROFILE} ${TMLTFILE} in=200 out=400
# must have profile here, for checking w/ -consumer xml (else segfault)
# this command may add additional producers to the xml!:
## melt -profile ${PROFILE} ${TMLTFILE} -consumer xml
# use this to generate xml if needed:
#melt -profile ${PROFILE} $(cat ${TMLTFILE} | tr '\n' ' ') -consumer xml
# if exited normally, cleanup:
finished
答案4
已經有一段時間了,但我會嘗試以對我有用的方式回答標題問題。
這是相關的:為什麼 BASH 進程替換不適用於某些命令?
所以我試著解決的具體問題是:
- 我有一個圖像轉換器;
- 它從[插入隨機格式]轉換為BMP/PNM/TGA等簡單格式;
- 我想轉換為 JPEG,因此需要將其與 ImageMagick 連結
convert
; - 我不想使用臨時文件。
因此,不幸的是,該工具不喜歡輸出到 stdout/fds/pipes,因為它從輸出檔案名稱的副檔名派生輸出格式。那麼如何欺騙它呢?
建立具有適當副檔名的符號連結/dev/fd/N
並將其用作「臨時檔案」。
例子:
ln -s /dev/fd/4 temp.pnm
[TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]