测试bash中是否至少存在一个带有名称前缀的目录

时间:2018-12-04 03:01:07

标签: linux bash shell

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

此代码如下:

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)的情况下,对任意数量的目录进行此项操作?

3 个答案:

答案 0 :(得分:2)

作为一种可行的替代方案(仅兼容bash,不兼容/bin/sh),请考虑:

if dirs=( "$name"*/ ) && [[ -d ${dirs[0]} ]]; then
  echo "Directories starting with $name already exist"
fi
  • 数组分配可与任意多个匹配项一起使用
  • ...但是,仅当glob成功扩展后,数组中的第一个条目才是有效目录(并且glob表达式中的尾随/阻止了它扩展为除以外的任何内容目录,因此,如果结果中根本没有目录,您就知道它扩展到的 all 元素都是目录。

如果您还需要适用于/bin/sh的功能,请考虑以下功能:

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

之所以可行,是因为匹配列表扩展到了函数的参数列表,有效地替代了数组。


由于[是内置的shell,因此这些基于阻塞的方法的常数因子成本要比依赖于外部工具的方法低得多,这将使它们的整体速度大大提高(某些特殊情况,例如目录)如此之大以至于最好在找到第一个匹配项后停止;其中find . -name "$name*" -print -quit可能有用)。

答案 1 :(得分:0)

尝试这个。

#! /bin/bash -e
name='foobar'

if [ `find . -maxdepth 1 -type d -name "$name*" -print -quit` -gt 1 ]; then
  echo "Directories starting with $name already exist"
fi

答案 2 :(得分:0)

最简单的解决方案:

properties

(警告:在某些特殊情况下(文件名中的特殊字符等)可能不起作用