如何在多个条件下使用“if”命令?

如何在多个条件下使用“if”命令?

我该怎么做呢?

if [ -f town-*.swf ]
then
mkdir towns
fi

这会检查是否town-*.swf存在,但我还需要它来查找city-*.swf其他内容,所以我需要这样的东西:

if [ -f town-*.swf, city-*.swf ]
then
mkdir towns
fi

答案1

POSIXly,你可以使用ls

if ls town-*.swf >/dev/null 2>&1 &&
   ls city-*.swf >/dev/null 2>&1 
then
  mkdir towns
fi

或更短的 if 条件:

if ls town-*.swf city-*.swf >/dev/null 2>&1

即使你的 shell 支持大括号扩展:

if ls {town,city}-*.swf >/dev/null 2>&1

答案2

if stat -t city-*.swf >/dev/null 2>&1
then
    if stat -t town-*.swf >/dev/null 2>&1
    then
       mkdir towns
    fi
fi

正如用户 uwe 在评论中指出的那样,我之前的命令将阻止通配符扩展。然而,这个新版本应该可以工作。

如果您需要一个if循环,您可以将脚本修改为,

if stat -t city-*.swf >/dev/null 2>&1 && stat -t town-*.swf >/dev/null 2>&1
then
     mkdir towns
fi

如果您需要指定 or 条件而不是 and 条件,则可以替换&&||

测试

ls
city-1.swf  city-2.swf  city-3.swf  city-4.swf  city-5.swf  sc.sh  
town-1.swf  town-2.swf  town-3.swf  town-4.swf  town-5.swf

现在,我执行名为的脚本sc.sh,然后我可以看到城市目录已成功创建。

参考

https://stackoverflow.com/questions/2937407/test-whether-a-glob-has-any-matches-in-bash

答案3

在大多数情况下,命令test ( [ )提供操作员-a-o

EXPR1 -a EXPR2如果两者都为真表达式1表达式2是真的。
EXPR1 -o EXPR2如果有的话则为真表达式1或者表达式2是真的。

但在可能的多行情况下,您应该使用可以在条件下运行的命令(例如ls

ls {town,city}-*.swf &>/dev/null && mkdir town

你可以利用这样一个事实通配当找不到替换时,字符串保持原样(在 with 的情况下*)。所以我们只需要检查它是否在该行中:

set -- {city,town}-*.swf 
[[ ! "$*" =~ \* ]] && mkdir town

或使用case(如上面评论中提供的)

case $(ls) in
  *city-*.swf*town-*.swf*) mkdir town ;;
esac

答案4

这是一个比运行外部命令影响更小的解决方案ls,并且比基于stat(因操作系统而异)的解决方案更可移植。

#!/bin/bash

found=false
for _ in town-*.swf, city-*.swf do
  found=true; break
done

if $found; then
  echo "Yup!"
fi

下划线是一次性变量。循环for是扩展文件列表的简单方法,并确保break您不会浪费循环遍历长文件列表的周期。可执行文件true和可以在或false中找到,并且可以替换为/bin//usr/bin/bash 内建函数或函数如果您更喜欢这种优化。

请注意,这也应该适用于/bin/sh. (至少,它在其他几个操作系统中对我来说是这样的。)

相关内容