難読化されたファイルオープナーとして使用したい次のbashスクリプトがあります。 fifoを生成し、fzfを実行する新しい端末を作成し、fzfの出力をfifoにリダイレクトします。次に、fifoから読み込み、ファイルを開く関数を呼び出します。
私の問題は、関数内のwhileループがopen
終わらないことです。すべての行を読んだ後にFIFOを閉じる方法は?
#!/usr/bin/env bash
FIFO=/tmp/fuzzy-opener
[ -e "$FIFO" ] || mkfifo "$FIFO"
exec 3<> "$FIFO"
function open {
while read file; do
# open every $file based on its mime-type
done <&3
echo 'done' # this is never reached
}
alacritty -e sh -c "fzf -m >&3" \
&& open
答え1
read()
書き込みの終わりが閉じると、パイプにEOFが表示されます(0バイトの読み取りから返されます)。しかし、私の考えでは、<>
パイプは読み取り/書き込みモードで開かれているので、パイプには常に作成者があり、シェルはファイルハンドルを開いたままにしておくことです。
私はシェルでパイプを開くことをスキップして、次のことができるはずだと思います。
alacritty -e sh -c "fzf -m >$FIFO" && open < "$FIFO"
または、より適切には次のようになります。
alacritty -e sh -c 'fzf -m >"$1"' sh "$FIFO" && open < "$FIFO"
ここでは、質問の構成が異なる動作をしていると仮定します。敏捷性がバックグラウンドで端末を作成し、すぐに終了する場合は、そうする必要があります。そうでない場合は、alacritty -e sh ... & open < "$FIFO"
2つの部分を同時に実行する必要があります。
答え2
次の理由でいくつかの選択肢を提案します。
- あなたの質問のスクリプトによると、FIFOは本当に必要ではないようです。
- 原則としてBashを使用しているので、NUL文字を区切り文字(POSIXファイルパスで許可されていない唯一のバイト)として使用できますが、残念ながら
fzf
改行文字を含むファイル名には機能しないようです。 - ファイルから読み取ると、
/tmp
深刻なセキュリティ問題が発生する可能性があります。他の人がファイルを/tmp/fuzzy-opener
通常のファイルとして作成した場合、スクリプトはそのopen
内容に喜んで適用されます(一部のシステムでは、自分が所有していない単語書き込み可能な固定ファイルで開きます)。 )exec 3<>
willディレクトリを使用してくださいエラー発生)。
あなたはそれを使用することができます:
function open {
while IFS= read -r -d '' file
do
echo "$file" # Replace with the actual open action
done
}
alacritty -e sh -c 'fzf -m --disabled --print0 >&3' 3>&1 | open
-d ''
取り外して移植可能にして移植可能にすることができます--print0
(上記の制限を考慮すると何も失われませんfzf
)。または、配列を使用して選択したファイル名を保存します。
function open {
for file
do
echo "$file" # Replace with the actual open action
done
}
mapfile -t -d '' toopen < <(alacritty -e sh -c 'fzf -m --print0 >&3' 3>&1) &&
open "${toopen[@]}"
fzf
どちらの場合も、リーダーコマンドが接続されているパイプの書き込み端をコピーした新しいファイルディスクリプタに出力がリダイレクトされることが重要です。