我正在编写一个脚本,在系统中搜索文件,然后对每个文件进行一些完整性检查,如果它们通过了,我想在 fzf 中显示它们。当在 fzf 中单击该项目时,我想用程序运行该文件。
到目前为止,我有:
dir="/path/to/dir"
fd . $dir --size +1MB | while read -r line; do
file_type=$(file -b "$line")
echo "$line" | fzf
if [[ "$file_type" == "data" ]]; then
echo "$file_type"
fi
done
基本上,我在指定目录中搜索大于 1MB 的文件。对于每个文件,我运行文件命令并检查命令输出是否返回“数据”。如果是这样,我想将其添加到 fzf 列表中。然后,当我单击该项目时,我想使用应用程序运行具有完整路径的文件:例如myapp /path/to/file/selected/in/fzf
.
到目前为止的问题是 fzf 正在阻塞,我无法在循环中填充列表。我真的必须先将所有内容添加到数组中,然后将其通过管道传输到 fzf 吗?理想情况下,这应该并行发生,也就是说,我想在搜索仍在进行时动态添加新项目,而不是等待它完成。
我也不知道以后如何运行选定的文件。有人可以帮我弄这个吗?
fzf
不会阻碍您的思维方式。它完全能够即时添加到列表中。您可以在以下示例中看到这一点(pv
如果未安装,请先安装):其中
pv
每秒输出一行,这些行出现在 中fzf
,您可以上下移动选择并且没有任何阻塞。您的代码的问题是您
fzf
在while read …
循环内运行。对于每一行,您运行一个单独fzf
的仅获取该单行的行。循环只有在fzf
完成后才能继续。所以不是fzf
拒绝阅读更多;这是关于fzf
在循环中。基本上你想要这样的东西:
where
data_filter
是一段过滤行的代码。它可以是一个 shell 循环:作为过滤器,循环应该将您不想过滤掉的所有行(并且只有这些行)打印到其标准输出。它可以是一个名为
data_filter
. 在您的情况下,这是正确的功能:然后你将它用作管道中的过滤器。
现在我们有了
find … | data_filter | fzf
应该可以正常工作并打印您选择的任何路径名的管道。要对文件执行某些操作,请使用以下之一:find … | data_filter | fzf | xargs …
,其中xargs
配置为按原样读取整行。使用 GNUxargs
,如果您要运行的工具是ls -l
,这将是:但是因为
xargs
默认情况下会解释引号并执行其他操作(例如拆分),所以您需要很好地了解它的选项才能在这种情况下使用它。我承认我从来没有掌握过xargs
,我不确定我在这里使用了最好的一组选项。… | fzf | xargs ls -l
我的观点是:在许多情况下,一个简单的调用 like会中断。f="$(find … | data_filter | fzf)"
,然后"$file"
在任何你想要的地方使用。一个优点是您可以知道fzf
. 一个理论上的缺点是$()
带尾换行符。实际上,在我们的例子中,带有尾随(或任何)换行符的路径名data_filter | fzf
无论如何都不能很好地通过。例子:
由于管道中的所有工具都使用换行符来分隔条目,因此带有换行符的路径名会破坏代码。
要使用换行符处理路径名,您需要使整个管道使用以空字符结尾(与以换行符结尾相反)的条目。
首先,您需要
find … -print0
(或等效fd
命令)。注意一些find
不支持的实现-print0
(-exec printf '%s\0' {} +
可以替代)。那么新的过滤函数应该是:
下次使用
fzf --read0 --print0
。最后
xargs -r0 …
。(替代方案$()
很麻烦,我不会详细说明;在这种情况下更喜欢xargs -r0
。)请注意,这些选项不可移植,您xargs
可能不支持它们。作为奖励,它xargs -r0
可以很好地与fzf -m
.一个示例管道:
注释和有用的链接:
一般来说,过滤器可以内置
find …
(感谢find -exec
)。我没有这样做是因为您似乎想使用fd
,而我对这个工具还不够了解。如果您提早选择一个项目(即在
find
过滤器完成之前),那么fzf
管道中的每个节点都可能在退出之前find
退出。只有在尝试写入后,过滤器才会注意到fzf
不再存在;同样find
会在它尝试写入后注意到(比较这个答案)。这意味着find
可能会比它需要的工作时间更长,从而阻止 shell 继续执行脚本中的下一个命令(或显示提示,如果是交互式的)。您可以在后台运行一些部分:这不会阻止
find
过滤器在fzf
退出后工作,但整条线不会停止。外壳将在ls
完成其工作后立即继续运行。后台进程迟早会终止。引用正确。在您的问题中有未引用的
$dir
.为什么
printf
优于echo
?.了解
IFS= read -r line
。如何在 Bash 中使用空字节?