为什么当我直接使用而不使用变量时条件不起作用?

为什么当我直接使用而不使用变量时条件不起作用?

这给了我一个错误,说参数太多:

if [ $( file -b $i ) == "directory" ]

但是当我尝试这个时

name=$( file -b $i )
if [ name == "directory" ]

看起来效果很好。

有人可以解释这一点或在文档中指出解释吗?

答案1

有几个问题:

  • ][表示( )参数的结束test,并且它必须是最后一个参数;你有几个]s,这是错误的;大概你的意思是使用:

    if [ $( file -b $i ) == "directory" ]
    
  • 如果您使用了上面的内容,您会得到bash: [: too many arguments,因为分词将在变量扩展 ( ) 的输出上完成$i,然后进行命令替换$()( filecommand) ,并且[会在 之前看到多个单词=,从而导致错误消息。您需要引用变量扩展和命令替换:

    [ "$(file -b "$1")" == "directory" ]
    

作为旁注,您应该使用bash关键字[[,而不是[因为前者将为您处理单词拆分(和路径名扩展)。

答案2

if [ $( file -b $i ) == "directory" ]

这里有两个问题:

  • 使用 single=进行字符串比较。请man test参阅 正确的语法(注意,在许多情况下都有特定于 shell 的实现,因此如果您没有相关文档,[请参阅您的 shell 的语法)。如果您绝对需要,请使用它,这是许多类似 bourne shell 的功能,包括 bash、ksh、zsh。注意: while存在于 bash 中man pagetest==[[==从2.0版本开始, “= 应与测试命令一起使用以实现 POSIX 一致性。” (bash 手册页)。

  • 将所有变量引用为"$()".特别感兴趣的是$i$i由于 shell 的单词扩展,带空格的文件名会分成多个单词。

例子:

bash-4.3$ mkdir with\ space
bash-4.3$ i="./with space"
bash-4.3$ set -x
bash-4.3$ [ $( file -b $i ) == "directory" ] && echo "YES"
++ file -b ./with space
+ '[' cannot open '`./with'\''' '(No' such file or 'directory)' cannot open '`space'\''' '(No' such file or 'directory)' == directory ']'
bash: [: too many arguments

name=$( file -b $i )
if [ name == "directory" ]

这里的问题:

  • name没有扩展到变量,这里只是一个字符串“名称”。你需要"$name"再一次,单身=

另外,它不可能起作用,因为 的退出状态test返回为 false(退出状态 1)

$ name=$(file -b /etc)
$ set -x
$ [ name == "directory" ]
+ '[' name '==' directory ']'
$ echo $?
+ echo 1
1

以上在bashmkshshell 上进行了测试。

答案3

有很多问题!让我们看一下正在“工作”的部分:

 name=$( file -b $i )
 if [ name == "directory" ]

这将 file 命令的输出分配给名为 的变量name,但不使用它;相反,它运行[带有 3 个参数的命令:name==directory。接受==是 bash 扩展。

如果将其更正为使用$name而不是,在许多情况下name您会再次遇到问题。too many arguments这是因为file返回多个单词结果,例如ASCII text.所以命令运行后你会得到

if [ ASCII text == directory ]

现在很明显该命令缺少一些分组。

if [ "$(file -b -- "$i")" = "directory" ]

可能是您想要的:=而不是==为了可移植性,并引用命令替换的结果你几乎总是想做的事

相关内容