我有一个包含 3 个文件的目录:file1
以及file2
以下 bash 脚本:
#!/bin/bash
set -e
Command="ls -1 -I file1"
echo "Command: $Command"
Files=`$Command`
echo "Files:"
echo $Files
结果正如人们所预料的那样。即被file1
忽略并且不显示在列表中:
$ ./test.sh
Command: ls -1 -I file1
Files:
file2
test.sh
现在,如果我想支持忽略名称中带有空格的文件怎么办?我应该将文件名用引号引起来,对吗?出色地...
#!/bin/bash
set -e
Command="ls -1 -I 'file1'"
echo "Command: $Command"
Files=`$Command`
echo "Files:"
echo $Files
产量:
$ ./test.sh
Command: ls -1 -I 'file1'
Files:
file1
file2
test.sh
然而,直接在 bash 中计算相同的命令会产生正确的结果:
$ ls -1 -I 'file1'
file2
test.sh
这里发生了什么?添加引号似乎会使某些内容偏离轨道,但为什么呢?
用任何类似的命令替换命令都没有帮助:
Command="ls -1 -I \"file1\""
Command="ls -1 --ignore='file1'"
改变命令的评估也没有帮助:
Files=$($Command)
Files=$(`echo $Command`)
看来正确的行为只能通过引入eval
Files=$(eval $Command)
Files=`eval $Command`
我真的很想了解为什么要评估和执行,但不知何故,除非添加ls
,否则引用的参数会被忽略。eval
答案1
因为报价删除如果引用字符本身已被引用,则不会应用于引用字符。
在:
Command="ls -1 -I 'file1'"
单引号'
被双引号引用"
,因此它被视为字符串的一部分。您可以使用printf
with %q
(in bash
, ksh
and zsh
) 来检查:
$ printf '%q\n' "$Command"
ls -1 -I 'file1'
如果直接在终端中运行,则单引号不会被引用,并且会被 shell 删除。