无法确定何时将星号(*)作为参数传递给脚本

时间:2014-03-14 12:58:21

标签: bash shell

这是我的代码:

if [ "$#" -eq 0 ]; then
    echo "no params"
elif [ "$#" -eq 1 ]; then
    if [ "$1" = "*" ] ; then
    # do something
    else echo "bad params"
    fi
else echo "more than 1 param"
fi

问题是当我用

启动脚本时
 sh script.sh *   

它将打印超过1个参数cause the " * " will search for all files

我的问题是如何禁用搜索文件。

4 个答案:

答案 0 :(得分:2)

脚本无法判断它是否作为参数或文件列表传递了不带引号的*,因为在shell实际调用脚本之前,它会将*替换为列表该通配符匹配的文件。

因此,如果不要求用户引用,您所要求的行为是不可能的:

your-script '*'

答案 1 :(得分:2)

引用星号以防止外壳扩展

sh script.sh "*"

或首先禁用文件名生成:

set -f
sh script.sh *
set +f          # Re-enable afterwards

第二种方法并不是真的值得推荐的;关闭文件名扩展可能会在以后产生意想不到的后果,与简单引用星号相比,它打字很多。

答案 2 :(得分:0)

您必须引用星号*,否则它会扩展到当前目录中的文件(请参阅globbing)。

$ sh script.sh "*"

答案 3 :(得分:0)

试试这个:

$ echo *   # Note: No quotation marks

您将获得文件和目录的列表。

现在试试这个:

$ echo "*"   # Note the quotes around the asterisk

在这里,你只会得到一个星号。

在程序执行之前,shell会抓取参数并展开它们。

这是因为Unix中的shell非常智能。它很好,因为这意味着我的程序不必解释*.txt的含义。 shell处理它。这也意味着如果我想将*传递给shell脚本,我需要引用它。

报价通常可以通过三种方式完成:

  • 使用双引号$echo "*"
  • 使用单引号:`$ echo' *'
  • 使用反斜杠$echo \*

使用双引号几乎是标准。它并没有完全阻止shell破坏你的命令行。 shell将插入shell变量,但它将停止所谓的 globbing ,其中shell将尝试将专用字符扩展为文件名。

$ foo="bar"
$ echo "$foo *"
$ echo bar *

使用单引号将使shell完全不受影响。它甚至不会尝试插入变量。

$ foo="bar"
$ echo '$foo *'
$foo *

使用反斜杠可防止shell对下一个字符执行任何操作。它就像单引号,但你不必担心结束语:

$ echo \$foo \*
$ $foo *

因此,您的shell脚本没有任何问题。您的shell脚本正在检测是否正在向其传递星号。问题是shell正在拦截您传递给命令的参数,看到星号,并在程序开始执行之前将其替换为目录中所有文件的列表。

您可以通过输入以下命令来查看:

$ set -xv

现在,尝试使用星号运行您的程序。

$ myprog *

set -xv命令将显示shell在程序执行之前传递给程序的内容。 set -xv,但他们的方式,在调试shell脚本时非常有用,所以很高兴知道。

要关闭set -xv,请输入:

$ set +xv