我的 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 界面,这样似乎就完成了,但我仍然必须等待命令find
完成(用 验证top
),这不知何故需要很长时间长的。我不太确定为什么;我想要的文件几乎总是立即出现。
我在上面添加了一些额外的行以避免 XY 问题。我对具有相同功能和更快执行速度的任何东西都很满意。
答案1
这里有两种可能性:要么fzf
在选择文件时实际上没有退出,要么在选择文件find
时没有退出fzf
。如果是后者,可以写一个脚本,退出find
时手动关闭。fzf
Linux 中管道的工作方式find
并不知道它正在写入的管道没有从该管道读取任何内容,直到它尝试写入该管道并失败为止。因此,如果您选择该文件后 find
已经找到了它要找到的所有内容,find
不再写入管道,因此将在退出之前迭代整个文件系统。
举例来说,如果您在中创建一个随机文件/
然后运行find / -name $random_file_name | head -n 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。与 Bash 的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'