如何使命令替换传递由空格分隔的单引号 POSIX 路径列表?
command1 $(command2)
command1 '/path/to/file 1' '/path/to/file 2' '/path/to/file 3'
我如何追踪扩展?
答案1
您可以使用 来准确查看正在运行的命令set -x
。一个相当愚蠢的例子:
$ echo $(echo "foo 'bar baz' taz\\ jaz")
foo 'bar baz' taz\ jaz
会给:
++ echo 'foo '\''bar baz'\'' taz\ jaz'
+ echo foo ''\''bar' 'baz'\''' 'taz\' jaz
foo 'bar baz' taz\ jaz
由于所有转义,这有点难以阅读。例如第二个词:
''
变得一无所有。\'
变成单引号 ('
)'bar'
变成bar
因此该参数作为 传递'bar
。您可以使用类似的内容进行确认(假设您安装了 Data::Dump,不幸的是,这不是默认设置)请注意,$(echo…
已将其逐字复制到 perl 行:
$ perl -MData::Dump=pp -E 'pp @ARGV' $(echo "foo 'bar baz' taz\\ jaz")
("foo", "'bar", "baz'", "taz\\", "jaz")
这里发生的是 bash 正在进行分词(基于 off $IFS
),而不是参数解析。因此,不幸的是,您可能必须使用eval
并处理由此带来的所有风险。
$ eval "echo $(echo "foo 'bar baz' taz\\ jaz")"
foo bar baz taz jaz
(另外,我会注意到,如果你可以让你的命令生成其输出作为名称列表,用 NUL 分隔,那就是简单的处理使用xargs -0
和进一步,完全安全)。
答案2
您很少能拥有可理解格式的文件列表xargs
。所以跑
command1 | xargs command2
请注意,在某些 UNIX 变体上,如果 的输出很大,由于命令行长度限制,command1
将无法使用所有文件名运行。command2
使用的缺点xargs
是它会多次运行命令而不是正确报告错误。您可以使用 检查命令行长度限制getconf ARG_MAX
。
答案3
尝试这样的事情:-
path1="/etc/passwd"
path2="/var/log/secure"
[root@localhost base_filters]# ls -l "$path1" "$path2"
-rw-r--r--. 1 root root 1876 Mar 10 22:15 /etc/passwd
-rw-------. 1 root root 2408 Apr 5 23:09 /var/log/secure
答案4
尝试使用 IFS 变量,这样空间就不会影响您的脚本。我会将 IFS 存储在变量中,并在完成脚本操作后恢复 IFS。