选择文件到数组后,允许用户完成parallel/xargs命令(功能);在printf脚本中正确引用nul [英] allow user to complete parallel / xargs command (function) after selecting files into array; quoting nuls correctly in printf script

查看:140
本文介绍了选择文件到数组后,允许用户完成parallel/xargs命令(功能);在printf脚本中正确引用nul的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是在这个问题中,我可以将选定的文件放入数组中,并将它们传递给命令/函数(已导出).这个问题的不同之处在于,我希望用户在选择文件后完成命令.

In that question, I could get selected files into an array and pass them to a command / function (already exported). This question differs in that I would like the user to complete the command after selecting the files.

主要目的:向我展示一个文件名列表(FZF).我手动选择其中一些.然后FZF将此子集放入数组.然后,我想编写一条未完成的命令,希望用户完成该命令并按Enter.

Main Aim: I am presented with a list of filenames (FZF). I manually select some of these. FZF then puts this subset into an array. I then want to compose an unfinished command which expects the user to complete the command and press Enter.

文件名中可以​​有空格;因此选择以Null分隔.

The filenames can have spaces in them; hence the choice of Null-separated.

我正在使用FZF选择文件.我认为它会生成一个包含无尾文件名的数组.但是FZF产生的第一项是按键的名称.这就是为什么脚本将FZF输出的第一项不同对待的原因.

I'm using FZF to select the files. It produces an array containing nul-ending filenames, I think. But the first item that FZF produces is the name of a key-press. That's why the script treats the first item of FZF's output differently.

当前我有

#!/bin/bash
readarray -d '' out < <(fd .|fzf  --print0 -e -m  --expect=ctrl-e,ctrl-l)
if [ ${#out[@]} -eq 0 ]; then return 0
fi
declare -p out
key="$out"
y=${out[@]:1}
if [ ${#y[@]} -eq 0 ]; then return 0
fi
case "$key" in
ctrl-e ) echo do something ;;
ctrl-l ) echo do something else ;;
* )
printf -v array_str '%q ' "${y[@]}"
cmd="printf '%s\0' ${array_str} | parallel -0 wc"
read -e -i "$cmd" cmd_edited; eval "$cmd_edited" ;; #not working
esac

我已经接近了:该命令看起来应该正确,但是NUL值却不起作用. 最后一行不起作用.它旨在将文件数组打印在具有空分隔符的行上,并且仍然允许用户在单击Enter之前指定一个函数(已导出). parallel命令会将功能应用于数组中的每个文件.

I have gotten close: the command looks like it should, but the NUL values are not behaving. The last line doesn't work. It is intended to print the array of files on a line with null separator and still allow the user to specify a function (already exported) before hitting Enter. The parallel command would apply the function to each file in the array.

$ls
file 1
file 2
...
...
file 100

当前,如果我选择file 3file 2,则脚本的输出如下所示:

Currently, if I choose file 3 and file 2, the output of my script looks like this:

printf "%s\0" file 3 file 2 | parallel -0

后面附加wc

但是在我键入wc并按Enter之后,我得到以下结果:

But then after I type wc and press Enter I get the following result:

printf "%s\0" file 3 file 2 | parallel -0 wc
wc: file030file020: No such file or directory

编辑:我现在加入了declare -p out行,以明确FZF在生产什么. 现在出现的结果,使用下面的Charles修改:

Edit: I have now included the line declare -p out to make clear what FZF is producing. The results as they now appear, using Charles' modification below is:

declare -a out=([0]="" [1]="file 3" [2]="file 2" [3]="file 1")
printf '%s\0' file\ 3\ file\ 2\ file\ 1  | parallel -0 wc
wc: file030file020file010: No such file or directory

因此,nul显然出了问题.

So something has obviously gone wrong with the nuls.

如何修复代码?

推荐答案

忽略fzfparallel是否满足您的要求,以下内容肯定不会:

Ignoring whether fzf and parallel do what you want, the following quite certainly doesn't:

cmd="printf \"%s\0\" ${y[@]} | parallel -0 wc"

为什么?因为${y[@]}不会插入使y数组的内容表示为有效的shell语法所必需的引号和转义符(当通过eval进行反馈时引用数据的原始内容).

Why? Because ${y[@]} doesn't insert quoting and escaping necessary to make the contents of the y array be expressed as valid shell syntax (to refer to the data's original contents when fed back through eval).

如果要将数据插入要解析为代码的字符串中,则需要先对其进行转义. Shell可以使用printf %q:

If you want to insert data into a string that's going to be parsed as code, it needs to be escaped first. The shell can do that for you using printf %q:

printf -v array_str '%q ' "${y[@]}"
cmd="printf '%s\0' ${array_str} | parallel -0 wc"
IFS= read -r -e -i "$cmd" cmd_edited; eval "$cmd_edited"

这篇关于选择文件到数组后,允许用户完成parallel/xargs命令(功能);在printf脚本中正确引用nul的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆