首页 > 解决方案 > 测试bash中是否至少存在一个带有name前缀的目录

问题描述

我有一个用户输入名称的脚本,并想确定是否存在以该名称开头的任何目录。

此代码如下所示:

runTest() {
  if test -d "$name"*; then
    echo "Directories starting with $name already exist"
  fi
}

如果只有一个这样的目录,它工作正常:

name=foobar
rm -rf foobar*
mkdir foobar1
runTest # now the code will work

...但是如果有多个匹配项则不起作用:

name=foobar
rm -rf foobar*
mkdir foobar1 foobar2
runTest # now the code will emit an error: "test: too many arguments"

在不假设其中一个匹配项将始终包含特定数字(如 )的情况下,如何使其适用于任意数量的目录1

标签: linuxbashshell

解决方案


作为一个工作(仅 bash - 不/bin/sh兼容)替代方案的示例,请考虑:

if dirs=( "$name"*/ ) && [[ -d ${dirs[0]} ]]; then
  echo "Directories starting with $name already exist"
fi
  • 数组分配适用于任意数量的匹配项
  • ...但是只有当 glob 成功扩展时,数组中的第一个条目才是有效的目录(并且/glob 表达式中的尾随阻止它扩展到目录以外的任何内容,所以如果结果有任何目录,你知道它扩展到的所有元素都是目录)。

如果您也需要一些适用的东西/bin/sh,请考虑以下功能:

directoriesExist() { [ -d "$1" ]; }
if directoriesExist "$name"*/;  then
  echo "Directories starting with $name already exist"
fi

这是有效的,因为匹配列表扩展到函数的参数列表,有效地作为数组的替代品。


因为[是内置的 shell,这些基于 globbing 的方法比依赖外部工具的方法具有更低的常数因子成本,这将使它们总体上更快(除了一些极端情况,例如目录太大以至于最好在之后停止找到第一个匹配项;find . -name "$name*" -print -quit可能有用的地方)。


推荐阅读