Bash shell中的`if`命令返回某些内容,那么就执行某些操作

21

我正在尝试使用if/then语句,在ls | grep something命令有非空输出时执行一些语句。我不知道应该使用什么语法。我已经尝试了几种变体:

if [[ `ls | grep log ` ]]; then echo "there are files of type log";

http://mywiki.wooledge.org/BashFAQ/004(“如何检查目录是否为空?如何检查是否有任何*.mpg文件,或计算它们的数量?”)与手头的问题有些相关。 - Charles Duffy
3个回答

33

嗯,差不多了,但你需要用fi来结束if

另外,if只是运行一个命令,并且在命令成功执行(退出状态码为0)时执行条件代码,而grep只有在找到至少一个匹配项时才会执行。所以你不需要检查输出:

if ls | grep -q log; then echo "there are files of type log"; fi

如果你的系统上安装的是旧版或非 GNU 版本的 grep,不支持 -q("quiet")选项,你可以通过将其输出重定向到 /dev/null 来实现相同的结果:

if ls | grep log >/dev/null; then echo "there are files of type log"; fi

在这种特定情况下,你可以完全不用 grep,因为 ls 如果找不到指定的文件名会返回非零值,就像 D.Shawley 的回答中所示:
if ls *log* >&/dev/null; then echo "there are files of type log"; fi

但在Zsh中,或者在设置了failglob选项的Bash中,如果通配符没有匹配任何内容,这样的命令将会出错,而不会实际运行ls。你可以利用这种行为来检查,而根本不需要ls

# Zsh, or Bash with failglob set
if (echo *log*) >&/dev/null; then
  echo "there are files of type log"
fi

或者你可以设置nullglob

# with 'nullglob' set, in either Bash or Zsh
for f in *log*; do
  echo "There are files of type log"
  break
done

在Ksh或Bash中,如果没有设置任何选项,那么需要做更多的工作:
# Ksh or Bash without failglob or nullglob
for f in *log*; do 
  # even if there are no matching files, the body of this loop will run once
  # with $f set to the literal string "*log*", so make sure there's really
  # a file there:
  if [ -e "$f" ]; then 
    echo "there are files of type log"
    break
  fi
done 

4

或者不使用if; then; fi

ls | grep -q log && echo 'there are files of type log'

甚至可以这样做:
ls *log* &>/dev/null && echo 'there are files of type log'

你的意思是 >&,而不是 &> - Mark Reed

2
if 内置命令执行 shell 命令,并根据命令的返回值选择块。ls 如果找不到请求的文件,则返回一个独特的状态代码,因此不需要 grep 部分。 [[ 实用程序实际上是来自 bash 的内置命令,它执行算术运算。我可能在那部分上错了,因为我很少偏离 Bourne shell 语法。
无论如何,如果您将所有这些组合在一起,那么最终会得到以下命令:
if ls *log* > /dev/null 2>&1
then
    echo "there are files of type log"
fi

谢谢您的解释,但我更倾向于使用grep。我打算通过几个正则表达式规则进行过滤,并可能从除ls之外的其他命令中过滤输出。我使用ls作为示例,以便解决我的格式问题将允许我编写更多类似的命令。干杯,~) - Billy Moon
1
@BillyMoon - 你可能想考虑使用find而不是grep ls的输出。如果你确实要使用ls,请使用完整路径,这样你就不会被别人对ls的别名所困扰。 - D.Shawley
1
@D.Shawley 你也可以直接使用 command ls 命令,这将绕过别名和函数,而无需依赖于特定路径来执行该命令。 - Mark Reed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接