使用進程替換來欺騙需要文件的程序,並以特定擴展名作為參數?

使用進程替換來欺騙需要文件的程序,並以特定擴展名作為參數?

這是我的用例:命令列實用程式可以接受帶有命令列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 檔案系統:

  • 執行者— 讓您可以使用 shell 腳本建立簡單的 FUSE 驅動程式
  • AVFS或其他透明解壓縮檔案的 FUSE 檔案系統:將註解的剝離定義為解壓縮規則。

答案2

使用zshshell,您可以使用=(...)進程替換的形式(使用臨時檔案而不是/dev/fd/x檔案和管道),您可以為其指定後綴:

(TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))

有關詳細信息,請參閱info zsh TMPSUFFIX(假設info頁面已安裝,您可能需要安裝軟體包zsh-doc)。

答案3

好吧,事實證明,在我的具體情況下,這些熔化腳本將被嚴格解釋為命令列參數;所以僅僅sedOP中的一個並不能完全解決它(另外,還有其他東西,例如可以設定的設定檔)。所以這就是我最終所做的 - 可能可以在 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 進程替換不適用於某些命令?

所以我試著解決的具體問題是:

  1. 我有一個圖像轉換器;
  2. 它從[插入隨機格式]轉換為BMP/PNM/TGA等簡單格式;
  3. 我想轉換為 JPEG,因此需要將其與 ImageMagick 連結convert
  4. 我不想使用臨時文件。

因此,不幸的是,該工具不喜歡輸出到 stdout/fds/pipes,因為它從輸出檔案名稱的副檔名派生輸出格式。那麼如何欺騙它呢?

建立具有適當副檔名的符號連結/dev/fd/N並將其用作「臨時檔案」。

例子:

ln -s /dev/fd/4 temp.pnm
[TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]

相關內容