你需要了解Unix如何解释你的输入。
标准的Unix shell在将参数传递给程序之前插值环境变量和所谓的通配符,这与Windows有些不同,因为它使程序解释扩展。
尝试一下:
$ echo *
这将回显您当前目录中的所有文件和目录。在 echo
命令执行之前,Shell 插值并扩展了 *
,然后将扩展后的参数传回给您的命令。您可以通过执行以下命令来查看其工作方式:
$ set -xv
$ echo *
$ set +xv
set -xv
命令可以开启
xtrace 和
verbose。Verbose 会输出输入的命令,而
xtrace 则会输出经过 shell 展开后即将执行的命令。现在试一下:
$ echo "*"
请注意,将某些内容放入引号中可以隐藏来自shell的glob表达式,shell无法展开它。请尝试以下操作:
$ foo="this is the value of foo"
$ echo $foo
$ echo "$foo"
$ echo '$foo'
请注意,Shell 仍然可以在双引号中扩展环境变量,但不能在单引号中扩展。
现在让我们看一下您的语句:
file="home/edward/bank1/fiche/Test*"
双引号可以避免 shell 展开“glob 表达式”,因此变量“file”等于字面值“home/edward/bank1/finche/Test*”。因此,您需要执行以下操作:
file=/home/edward/bank1/fiche/Test*
缺少引号(和重要的斜杠!)现在将使文件等于与该表达式匹配的所有文件。 (可能不止一个!)如果没有文件,根据shell及其设置,shell可能仍将文件设置为该文字字符串。
你肯定有正确的想法:
file=/home/edward/bank1/fiche/Test*
if test -s $file
then
echo "found one"
else
echo "found none"
fi
然而,如果有多个文件,您仍然可能会得到 未找到 的返回结果。相反,您的 test
命令可能会因为参数过多而出现错误。
解决这个问题的方法之一是:
if ls /home/edward/bank1/finche/Test* > /dev/null 2>&1
then
echo "There is at least one match (maybe more)!"
else
echo "No files found"
fi
在这种情况下,我利用了
ls
命令的退出代码。如果
ls
找到一个可以访问的文件,它将返回零退出代码。如果它不能找到匹配的文件,则返回非零退出代码。
if
命令仅执行命令,然后如果命令返回零,则假定
if
语句为
true并执行
if
子句。如果命令返回非零值,则假定
if
语句为false,并执行
else
子句(如果有的话)。
test
命令以类似的方式工作。如果
test
为真,则
test
命令返回零。否则,
test
命令返回一个非零值。这与
if
命令非常搭配。事实上,有一个
别名到
test
命令。尝试这个:
$ ls -li /bin/test /bin/[
i
命令会打印出 inode。 inode 是文件的真实 ID。具有相同 ID 的文件是相同的文件。你可以看到,/bin/test
和 /bin/[
是相同的命令。这使得以下两个命令相同:
if test -s $file
then
echo "The file exists"
fi
if [ -s $file ]
then
echo "The file exists"
fi