测试一个glob是否在bash中有任何匹配 - 使用变量

时间:2014-03-07 05:40:05

标签: bash shell glob

我正在尝试这个问题中提出的答案:Test whether a glob has any matches in bash

if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
    echo found
else
    echo not found
fi

但是,我在带变量的脚本中这样做。

#!/bin/sh
directory=~/nd
glob="*12*.idx"
cd $directory
if test -n "$(find . -maxdepth 1 -name \"$glob\" -print -quit)"
then
    echo found
else
    echo not found
fi

运行脚本会给我:

not found

但是自己运行命令

find . -maxdepth 1 -name "*12*.idx" -print -quit

给我一​​个结果

./notes_archive_2012.idx

这是引用问题吗?

3 个答案:

答案 0 :(得分:1)

是的,这是一个引用问题。报价不应在$(...)内转义。考虑:

test -n "$(find . -maxdepth 1 -name \"$glob\" -print -quit)" # Wrong

在上面的表格中,-name看到的find的参数以文字双引号开头和结尾。如果文件名本身以双引号开头和结尾,它只匹配文件名。

以下是您想要的:

test -n "$(find . -maxdepth 1 -name "$glob" -print -quit)" # Right

来自man bash

  

使用$(命令)表单时,括号之间的所有字符   使          命令;没有人受到特别对待。

换句话说,如果你想在$(...)内的命令中使用双引号,只需使用双引号。 $(...)中的命令应该像在命令行中单独输入一样编写。

答案 1 :(得分:0)

您可以在没有外部命令的情况下执行此操作。一种方法是滥用for循环:

# Use the loop as a context for expanding the glob, not actually iterating
# over the results.
for f in $glob; do
    if [[ -f "$f" ]]; then
        echo found
    else
        echo not found
    fi
    break
done

您也可以使用数组:

files=( $glob )
if [[ -f "${files[0]}" ]]; then
    echo found
else
    echo not found
fi

答案 2 :(得分:0)

查找适用于本地文件但不适用于远程文件的文件或任何其他文件本地不存在的文件。有时您想要检查任意匹配,并且模式是字符串。

bash支持[[ "$string" == shellmatch* ]][[ "$string" =~ ^regexmatch.* ]]但不支持任何形式的[[ "$string" == "$shellmatch" ]],其中match参数是字符串。我还没有找到任何方法来欺骗bash处理字符串,而不是写出正确格式化的新shell脚本,并且我不相信空格或]]括号将得到正确支持。

Rich’s sh (POSIX shell) tricks是一个单行程,可以使用大多数POSIX shell,只使用大小写和一些聪明的引用。测试使用bash,sh。测试不适用于zsh。

fnmatch () { case "$2" in $1) return 0 ;; *) return 1 ;; esac ; }

我使用这个变体,所以我可以得到空白以匹配所有

fnmatch () { [ -z "$1" ] && return 0; case "$2" in $1) return 0 ;; esac; return 1 ; }

Examples:

fnmatch 'ab \?def' 'ab ?def'    && echo 'matched' # \ supported
fnmatch 'ab ?def' 'ab cdef'     && echo 'matched' # ? supported
fnmatch 'ab [cd]def' 'ab cdef'  && echo 'matched' # [] supported
fnmatch 'ab {c,d}def' 'ab cdef' && echo 'matched' # case does not support brace expansion
fnmatch 'ab c*' 'ab cdef'       && echo 'matched' # space supported
fnmatch 'ab) c*' 'ab) cdef'     && echo 'matched' # ) supported, does not interfere with case