プロセス置換を使用して、引数として特定の拡張子を持つファイルを期待するプログラムを騙しますか?

プロセス置換を使用して、引数として特定の拡張子を持つファイルを期待するプログラムを騙しますか?

これが私の使用例です: コマンドライン ユーティリティは、コマンドラインでmelt拡張子付きのファイル名を受け入れて.melt開くことができます。例として、これは適切なtest_p.meltファイルです:

colour:blue
out=24

colour:red
out=48

... を開いて遊びますmelt test_p.melt

さて、問題は、.meltファイルがコメントをサポートしていないことです。コメントをサポートしていればよかったのですが ( などの引数を含む、解析できない引数を含む行に対してはエラー メッセージが表示されます#)。コメント付きの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

... しかし、まず、ここには 2 つのコマンドがあり、1 行のパイプラインが必要です。また、後で一時ファイルを削除することを考えなければならないという別の問題が発生しますが、これは好ましくありません。

これは、Bash プロセス置換、または何らかの方法で標準の Linux ツールで可能ですか?

答え1

可能性としては、meltファイルの変更されたコピーを表示するファイルシステムを指すことが挙げられます。ヒューズ通常のプログラムで実装され、権限を必要としないファイルシステムドライバを構築する一般的な方法です。多くのFUSEファイルシステム、そのうちの 1 つが役に立つ可能性は十分にあります。アイデアは、.meltファイルを読み取るときに「実際の」ファイルを読み取り、コメントを除外するマウント ポイントを提供することです。

スクリプトFS有望そうです (ただし、使用したことはありません)。次のようなものが機能するはずです:

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 ファイルシステム:

  • 実行ヒューズ— シェルスクリプトを使用してシンプルなFUSEドライバを構築できます
  • AVFSまたは、ファイルを透過的に解凍するその他の FUSE ファイルシステム: コメントの削除を解凍ルールとして定義します。

答え2

シェルでは、サフィックスを指定できるプロセス置換形式 (ファイルとパイプの代わりに一時ファイルを使用する形式)zshを使用できます。=(...)/dev/fd/x

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

詳細については、info zsh TMPSUFFIXinfoページがインストールされていると仮定して、パッケージをインストールする必要がある可能性があります)を参照してください。zsh-doc

答え3

わかりました。私の特定のケースでは、これらの種類のメルト スクリプトは厳密にコマンド ライン引数として解釈される必要があることがわかりました。そのため、sedOP のスクリプトだけでは十分ではありません (さらに、プロファイルなど、設定できる他のものもあります)。そのため、最終的に私が行ったことは次のとおりです。これは、OP のタイトルがカバーする他のケースのインスピレーションとして役立つ可能性があります。

最終的に、次のようにすることに決めました。test.shmeltファイル (実際にはbashコメント付きのmeltスクリプト コードを含むスクリプト) を作成し、このファイルを実行可能にしchmod +x test.shmelt、スクリプトを編集した後、 として実行します./test.shmelt

test.melt実行すると、に「クリーンアップされた」ファイルが作成され/tmpmelt代わりにこのファイルが呼び出されます。 は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]

関連情報