私のUbuntuコンピュータには、次の行を含む見苦しいbashスクリプトがあります。
search_command="find -L $(printf "%q" "$search_folder") \( ! -regex '.*/\..*/..*' \) -mindepth 1 2> /dev/null"
for i in "${IGNOREENDINGS[@]}"
do
search_command="$search_command -not -name \"*$i\""
done
search_command="$search_command | sed 's|^${search_folder}/\?||'"
choice=$(eval "$search_command"|fzf -q "$file_query" -1 --preview "preview $search_folder {}")
fzf
このスクリプトを使用すると、コマンド一致を使用してファイルを選択できますGNU find
。
これには次の問題があります。スクリプトインタフェースでファイルを選択するとすぐに、fzfインタフェースが閉じて完了したように見えますが、まだコマンドが完了するfzf
まで待つ必要があります(validationを含む)。長期。なぜ私が望むファイルがほぼ常にすぐに現れるのか分かりません。find
top
XYの問題を避けるために上記の数行を追加しました。同じ機能とより速い実行を提供するすべてが満足です。
答え1
これには2つの可能性があります。fzf
ファイルを選択したときに実際にシャットダウンがないか、ファイルを選択したときfind
にシャットダウンがありませんfzf
。後者の場合は、find
終了時に手動で閉じるスクリプトを作成できます。fzf
Linuxでパイプがどのように機能するかは、find
パイプに書き込もうとし、失敗するまでパイプがパイプから何も読み取らないことを知りません。だからファイルを選択すると後ろに find
探しているものがすべて見つかった場合、find
パイプへの書き込みは行われなくなり、終了する前にファイルシステム全体が繰り返されます。
たとえば、任意のファイルを作成して/
実行すると、find / -name $random_file_name | head -n 1
非常に迅速に取得できるすべての出力が得られますが、プログラムは長時間実行され続けます。
この問題を解決する1つの方法は、プロセスが完了したときにプロセスを直接終了することです。場合によっては、最も簡単な方法はおそらく名前付きパイプです。
tmp_fifo=`mktemp -u`
mkfifo "$tmp_fifo"
eval "$search_command" > "$tmp_fifo" &
choice="$(fzf -q "$file_query" -1 --preview "preview $search_folder {}" < "$tmp_fifo")" ; kill $!
rm "$tmp_fifo"
これにより、一時的な名前付きパイプが作成され、そこに書き込んでfind
読み込みfzf
ます。ただし、fzf
終了すると、kill $!
実行は$!
最後に開始されたバックグラウンドプロセスを表します。この場合はfind
。
答え2
もう一つの答えよさそうだが、FIFOを管理しなければならないというのが欠点ですね。バッシュとcoproc
FIFOの名前を指定しなくても問題を解決できます。
(注:この回答が特定の問題ではなく一般的な問題を解決できるようにするために、変数とeval
同様の項目を削除しました。)
coproc find ... # this silently runs in background, no `&' nor explicit redirection needed
<&${COPROC[0]} fzf ... # piping from `find' to `fzf'
kill $! # killing the last background process, i.e. `find'