检查在shell脚本中是否存在通配符。

时间:2022-01-24 11:49:22

I'm trying to check if a file exists, but with a wildcard. Here is my example:

我试图检查一个文件是否存在,但是使用通配符。这是我的例子:

if [ -f "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

I have also tried it without the double quotes.

我也试过没有双引号。

21 个解决方案

#1


308  

The simplest should be to rely on ls return value (it returns non-zero when the files do not exist):

最简单的应该是依赖ls返回值(当文件不存在时它返回非零值):

if ls /path/to/your/files* 1> /dev/null 2>&1; then
    echo "files do exist"
else
    echo "files do not exist"
fi

I redirected the ls output to make it completely silent.

我重定向ls输出,使其完全保持沉默。


EDIT: Since this answer has got a bit of attention (and very useful critic remarks as comments), here is an optimization that also relies on glob expansion, but avoids the use of ls:

编辑:由于这个答案已经引起了一些关注(和非常有用的评论评论),这里的优化也依赖于glob的扩展,但是避免了ls的使用:

for f in /path/to/your/files*; do

    ## Check if the glob gets expanded to existing files.
    ## If not, f here will be exactly the pattern above
    ## and the exists test will evaluate to false.
    [ -e "$f" ] && echo "files do exist" || echo "files do not exist"

    ## This is all we needed to know, so we can break after the first iteration
    break
done

This is very similar to @grok12's answer, but it avoids the unnecessary iteration through the whole list.

这与@grok12的答案非常相似,但它避免了整个列表中不必要的迭代。

#2


45  

If your shell has a nullglob option and it's turned on, a wildcard pattern that matches no files will be removed from the command line altogether. This will make ls see no pathname arguments, list the contents of the current directory and succeed, which is wrong. GNU stat, which always fails if given no arguments or an argument naming a nonexistent file, would be more robust. Also, the &> redirection operator is a bashism.

如果您的shell有一个nullglob选项,并且打开了它,那么一个不匹配任何文件的通配符模式将全部从命令行中删除。这将使ls看不到路径名参数,列出当前目录的内容并成功,这是错误的。GNU stat总是失败,如果没有参数或参数来命名一个不存在的文件,它将更加健壮。此外,>重定向操作符是一个bashism。

if stat --printf='' /path/to/your/files* 2>/dev/null
then
    echo found
else
    echo not found
fi

Better still is GNU find, which can handle a wildcard search internally and exit as soon as at it finds one matching file, rather than waste time processing a potentially huge list of them expanded by the shell; this also avoids the risk that the shell might overflow its command line buffer.

更棒的是GNU find,它可以在内部处理通配符搜索,并在找到一个匹配的文件时退出,而不是浪费时间处理由shell扩展的潜在的巨大列表;这也避免了shell可能溢出命令行缓冲区的风险。

if test -n "$(find /dir/to/search -maxdepth 1 -name 'files*' -print -quit)"
then
    echo found
else
    echo not found
fi

Non-GNU versions of find might not have the -maxdepth option used here to make find search only the /dir/to/search instead of the entire directory tree rooted there.

非gnu版本的find可能没有在这里使用的-maxdepth选项,它只能搜索/dir/to/search,而不是根目录下的整个目录树。

#3


35  

Here is my answer -

这是我的答案。

files=(xorg-x11-fonts*)

if [ -e "${files[0]}" ];
then
    printf "BLAH"
fi

#4


17  

for i in xorg-x11-fonts*; do
  if [ -f "$i" ]; then printf "BLAH"; fi
done

This will work with multiple files and with white space in file names.

这将使用多个文件,并在文件名中使用空格。

#5


13  

UPDATE:

更新:

Okay, now I definitely have the solution:

好的,现在我有了解决方案:

files=$(ls xorg-x11-fonts* 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
   echo "Exists"
else
    echo "None found."
fi

> Exists

#6


12  

Maybe this will help someone:

也许这会帮助到某人:

if [ "`echo xorg-x11-fonts*`" != "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

#7


10  

You can do the following:

你可以这样做:

set -- xorg-x11-fonts*
if [ -f "$1" ]; then
    printf "BLAH"
fi

This works with sh and derivates: ksh and bash. It doesn't create any sub-shell. $(..)and `...` commands create a sub-shell : they fork a process, and they are inefficient. Of course it works with several files, and this solution can be the fastest, or second to the fastest one.

这与sh和派生:ksh和bash一起工作。它不会创建任何子shell。(. .)和“美元……命令创建一个子shell:它们派生一个进程,并且效率低下。当然,它与几个文件一起工作,这个解决方案可以是最快的,也可以是最快的。

#8


5  

The question wasn't specific to Linux/Bash so I thought I would add the Powershell way - which treats wildcards different - you put it in the quotes like so below:

这个问题不是针对Linux/Bash的,所以我想我应该添加Powershell方式——它对通配符不一样——你把它放在引号里,如下所示:

If (Test-Path "./output/test-pdf-docx/Text-Book-Part-I*"){
  Remove-Item -force -v -path ./output/test-pdf-docx/*.pdf
  Remove-Item -force -v -path ./output/test-pdf-docx/*.docx
}

I think this is helpful because the concept of the original question covers "shells" in general not just Bash or Linux, and would apply to Powershell users with the same question too.

我认为这是有帮助的,因为原始问题的概念涵盖了“shell”,而不仅仅是Bash或Linux,而且也适用于具有同样问题的Powershell用户。

#9


3  

The bash code I use

我使用的bash代码。

if ls /syslog/*.log > /dev/null 2>&1; then 
   echo "Log files are present in /syslog/; 
fi

Thanks!

谢谢!

#10


3  

Strictly speaking, if you only want to print "Blah" here is the solution :

严格地说,如果你只想打印“Blah”这是解决方案:

find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 'BLAH' -quit

Here is another way :

这是另一种方法:

doesFirstFileExist(){
    test -e "$1"
}

if doesFirstFileExist xorg-x11-fonts*
then printf "BLAH"
fi

But I think the most optimal is as follow, because it won't try to sort file names :

但我认为最优的方法是遵循,因为它不会尝试对文件名进行排序:

if [ -z `find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 1 -quit` ]
then printf "BLAH"
fi

#11


2  

Here's a solution for your specific problem that doesn't require for loops or external commands like ls, find and the like.

这里有一个针对您的特定问题的解决方案,它不需要循环或像ls、find之类的外部命令。

if [ "$(echo xorg-x11-fonts*)" != "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

As you can see, it's just a tad more complicated than what you were hoping for, and relies on the fact that if the shell is not able to expand the glob, it means no files with that glob exist and echo will output the glob as is, which allows us to do a mere string comparison to check whether any of those files exist at all.

正如你所看到的,只是有点更复杂的比你所希望的,并依赖于这样一个事实,如果壳不能扩大水珠,水珠的存在意味着没有文件和回声将输出的水珠,这让我们做一个纯粹的字符串比较检查这些文件是否存在。

If we were to generalize the procedure, though, we should take into account the fact that files might contain spaces within their names and/or paths and that the glob char could rightfully expand to nothing (in your example, that would be the case of a file whose name is exactly xorg-x11-fonts).

如果我们要推广的过程,我们应该考虑到这一事实文件可能包含空间在他们的名字和/或路径,水珠char什么都理所当然地扩展到(在你的例子中,这将是一个文件的名字正是xorg-x11-fonts)。

This could be achieved by the following function, in bash.

这可以通过以下函数在bash中实现。

function doesAnyFileExist {
   local arg="$*"
   local files=($arg)
   [ ${#files[@]} -gt 1 ] || [ ${#files[@]} -eq 1 ] && [ -e "${files[0]}" ]
}

Going back to your example, it could be invoked like this.

回到您的示例,可以像这样调用它。

if doesAnyFileExist "xorg-x11-fonts*"; then
    printf "BLAH"
fi

Glob expansion should happen within the function itself for it to work properly, that's why I put the argument in quotes and that's what the first line in the function body is there for: so that any multiple arguments (which could be the result of a glob expansion outside the function, as well as a spurious parameter) would be coalesced into one. Another approach could be to raise an error if there's more than one argument, yet another could be to ignore all but the 1st argument.

水珠扩张应该发生在函数本身的正常工作,这就是为什么我把论点放在引号里,这就是第一行的函数体有:所以,任何多个参数(这可能是一团扩张的结果以外的功能,以及一个寄生参数)将合并成一个。另一种方法可能是,如果存在不止一个参数,则会引发错误,而另一个方法可能是忽略第一个参数。

The second line in the function body sets the files var to an array constituted by all the file names that the glob expanded to, one for each array element. It's fine if the file names contain spaces, each array element will contain the names as is, including the spaces.

函数体中的第二行将文件var设置为由glob扩展到的所有文件名组成的数组,每个数组元素对应一个数组。如果文件名包含空格,那么每个数组元素都会包含名称,包括空格。

The third line in the function body does two things:

函数体中的第三行做两件事:

  1. It first checks whether there's more than one element in the array. If so, it means the glob surely got expanded to something (due to what we did on the 1st line), which in turn implies that at least one file matching the glob exist, which is all we wanted to know.

    它首先检查数组中是否有多个元素。如果是这样,这意味着glob肯定会扩展到某些东西(由于我们在第一行中所做的事情),而这又意味着至少有一个文件与glob相匹配,这就是我们想要知道的。

  2. If at step 1. we discovered that we got less than 2 elements in the array, then we check whether we got one and if so we check whether that one exist, the usual way. We need to do this extra check in order to account for function arguments without glob chars, in which case the array contains only one, unexpanded, element.

    如果在步骤1。我们发现数组中有小于2个元素,然后我们检查是否有一个,如果这样,我们检查是否存在,通常的方式。我们需要做这个额外的检查,以解释没有glob chars的函数参数,在这种情况下,数组只包含一个未展开的元素。

#12


1  

I use this:

我用这个:

filescount=`ls xorg-x11-fonts* | awk 'END { print NR }'`  
if [ $filescount -gt 0 ]; then  
    blah  
fi

#13


1  

IMHO it's better to use find always when testing for files, globs or directories. The stumbling block in doing so is find's exit status: 0 if all paths were traversed successfully, >0 otherwise. The expression you passed to find creates no echo in its exit code.

在测试文件、全局或目录时,最好使用find。这样做的绊脚石是find的退出状态:如果所有路径都成功遍历,则>0。您传递的表达式在其退出代码中没有创建echo。

The following example tests if a directory has entries:

下面的示例测试目录是否有条目:

$ mkdir A
$ touch A/b
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty'
not empty

When A has no files grep fails:

当A没有文件grep失败:

$ rm A/b
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . || echo 'empty'
empty

When A does not exist grep fails again because find only prints to stderr:

当A不存在时,grep再次失败,因为只找到stderr的输出:

$ rmdir A
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty' || echo 'empty'
find: 'A': No such file or directory
empty

Replace -not -empty by any other find expression, but be careful if you -exec a command that prints to stdout. You may want to grep for a more specific expression in such cases.

用任何其他的查找表达式替换-not -empty,但是要小心,如果你-exec命令打印到stdout。在这种情况下,您可能需要grep以获得更具体的表达式。

This approach works nicely in shell scripts. The originally question was to look for the glob xorg-x11-fonts*:

这种方法在shell脚本中很好地工作。最初的问题是寻找glob xorg-x11字体*:

if find -maxdepth 0 -name 'xorg-x11-fonts*' -print | head -n1 | grep -q .
then
    : the glob matched
else
    : ...not
fi

Note that the else-branched is reached if xorg-x11-fonts* had not matched, or find encountered an error. To distinguish the case use $?.

注意,如果xorg-x11-font *没有匹配,或者发现遇到错误,则会到达else-branched。区分这个案例使用$?。

#14


1  

if [ `ls path1/* path2/* 2> /dev/null | wc -l` -ne 0 ]; then echo ok; else echo no; fi

#15


0  

Try this

试试这个

fileTarget="xorg-x11-fonts*"

filesFound=$(ls $fileTarget)  # 2014-04-03 edit 2: removed dbl-qts around $(...)

edit 2014-04-03 (removed dbl-quotes and added test file 'Charlie 22.html' (2 spaces)

编辑2014-04-03(删除dbl-quotes并添加测试文件“Charlie 22”。html的(2个空间)

case ${filesFound} in
  "" ) printf "NO files found for target=${fileTarget}\n" ;;
   * ) printf "FileTarget Files found=${filesFound}\n" ;;
esac 

Test

测试

fileTarget="*.html"  # where I have some html docs in the current dir

FileTarget Files found=Baby21.html
baby22.html
charlie  22.html
charlie21.html
charlie22.html
charlie23.html

fileTarget="xorg-x11-fonts*"

NO files found for target=xorg-x11-fonts*

Note that this only works in the current directory, or where the var fileTarget includes the path you are want to inspect.

注意,这只能在当前目录中工作,或者var文件目标包含您要检查的路径。

#16


0  

If there is a huge amount of files on a network folder using the wildcard is questionable (speed, or command line arguments overflow).

如果使用通配符的网络文件夹上有大量的文件是可疑的(速度,或者命令行参数溢出)。

I ended up with:

我结束了:

if [ -n "$(find somedir/that_may_not_exist_yet -maxdepth 1 -name \*.ext -print -quit)" ] ; then
  echo Such file exists
fi

#17


0  

You can also cut other files out

你也可以删除其他文件。

if [ -e $( echo $1 | cut -d" " -f1 ) ] ; then
   ...
fi

#18


0  

Using new fancy shmancy features in ksh, bash, and zsh shells (this example doesn't handle spaces in filenames):

在ksh、bash和zsh shell中使用新的花哨的shmancy特性(这个示例不处理文件名中的空格):

# Declare a regular array (-A will declare an associative array. Kewl!)
declare -a myarray=( /mydir/tmp*.txt )
array_length=${#myarray[@]}

# Not found if the 1st element of the array is the unexpanded string
# (ie, if it contains a "*")
if [[ ${myarray[0]} =~ [*] ]] ; then
   echo "No files not found"
elif [ $array_length -eq 1 ] ; then
   echo "File was found"
else
   echo "Files were found"
fi

for myfile in ${myarray[@]}
do
  echo "$myfile"
done

Yes, this does smell like Perl. Glad I didn't step in it ;)

是的,这闻起来像Perl。很高兴我没有踩到它。

#19


0  

Found a couple of neat solutions worth sharing. The first still suffers from "this will break if there's too many matches" problem:

找到了一些值得分享的简洁的解决方案。第一个问题仍然是“如果有太多的匹配”问题,“这将会中断”:

pat="yourpattern*" matches=($pat) ; [[ "$matches" != "$pat" ]] && echo "found"

(Recall that if you use an array without the [ ] syntax, you get the first element of the array.)

(回想一下,如果使用一个没有语法的数组,就会得到数组的第一个元素)。

If you have "shopt -s nullglob" in your script, you could simply do:

如果你的脚本中有“shopt -s nullglob”,你可以简单地做:

matches=(yourpattern*) ; [[ "$matches" ]] && echo "found"

Now, if it's possible to have a ton of files in a directory, you're pretty well much stuck with using find:

现在,如果有可能在一个目录中有大量的文件,那么你就很容易被发现:

find /path/to/dir -maxdepth 1 -type f -name 'yourpattern*' | grep -q '.' && echo 'found'

#20


-1  

How about

如何

if ls -l  | grep -q 'xorg-x11-fonts.*' # grep needs a regex, not a shell glob
then
     # do something
else
     # do something else
fi 

#21


-14  

man test

人测试

if [ -e file ]; then
...  
fi

will work for dir\file.

将为dir \文件工作。

regards

问候

#1


308  

The simplest should be to rely on ls return value (it returns non-zero when the files do not exist):

最简单的应该是依赖ls返回值(当文件不存在时它返回非零值):

if ls /path/to/your/files* 1> /dev/null 2>&1; then
    echo "files do exist"
else
    echo "files do not exist"
fi

I redirected the ls output to make it completely silent.

我重定向ls输出,使其完全保持沉默。


EDIT: Since this answer has got a bit of attention (and very useful critic remarks as comments), here is an optimization that also relies on glob expansion, but avoids the use of ls:

编辑:由于这个答案已经引起了一些关注(和非常有用的评论评论),这里的优化也依赖于glob的扩展,但是避免了ls的使用:

for f in /path/to/your/files*; do

    ## Check if the glob gets expanded to existing files.
    ## If not, f here will be exactly the pattern above
    ## and the exists test will evaluate to false.
    [ -e "$f" ] && echo "files do exist" || echo "files do not exist"

    ## This is all we needed to know, so we can break after the first iteration
    break
done

This is very similar to @grok12's answer, but it avoids the unnecessary iteration through the whole list.

这与@grok12的答案非常相似,但它避免了整个列表中不必要的迭代。

#2


45  

If your shell has a nullglob option and it's turned on, a wildcard pattern that matches no files will be removed from the command line altogether. This will make ls see no pathname arguments, list the contents of the current directory and succeed, which is wrong. GNU stat, which always fails if given no arguments or an argument naming a nonexistent file, would be more robust. Also, the &> redirection operator is a bashism.

如果您的shell有一个nullglob选项,并且打开了它,那么一个不匹配任何文件的通配符模式将全部从命令行中删除。这将使ls看不到路径名参数,列出当前目录的内容并成功,这是错误的。GNU stat总是失败,如果没有参数或参数来命名一个不存在的文件,它将更加健壮。此外,>重定向操作符是一个bashism。

if stat --printf='' /path/to/your/files* 2>/dev/null
then
    echo found
else
    echo not found
fi

Better still is GNU find, which can handle a wildcard search internally and exit as soon as at it finds one matching file, rather than waste time processing a potentially huge list of them expanded by the shell; this also avoids the risk that the shell might overflow its command line buffer.

更棒的是GNU find,它可以在内部处理通配符搜索,并在找到一个匹配的文件时退出,而不是浪费时间处理由shell扩展的潜在的巨大列表;这也避免了shell可能溢出命令行缓冲区的风险。

if test -n "$(find /dir/to/search -maxdepth 1 -name 'files*' -print -quit)"
then
    echo found
else
    echo not found
fi

Non-GNU versions of find might not have the -maxdepth option used here to make find search only the /dir/to/search instead of the entire directory tree rooted there.

非gnu版本的find可能没有在这里使用的-maxdepth选项,它只能搜索/dir/to/search,而不是根目录下的整个目录树。

#3


35  

Here is my answer -

这是我的答案。

files=(xorg-x11-fonts*)

if [ -e "${files[0]}" ];
then
    printf "BLAH"
fi

#4


17  

for i in xorg-x11-fonts*; do
  if [ -f "$i" ]; then printf "BLAH"; fi
done

This will work with multiple files and with white space in file names.

这将使用多个文件,并在文件名中使用空格。

#5


13  

UPDATE:

更新:

Okay, now I definitely have the solution:

好的,现在我有了解决方案:

files=$(ls xorg-x11-fonts* 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
   echo "Exists"
else
    echo "None found."
fi

> Exists

#6


12  

Maybe this will help someone:

也许这会帮助到某人:

if [ "`echo xorg-x11-fonts*`" != "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

#7


10  

You can do the following:

你可以这样做:

set -- xorg-x11-fonts*
if [ -f "$1" ]; then
    printf "BLAH"
fi

This works with sh and derivates: ksh and bash. It doesn't create any sub-shell. $(..)and `...` commands create a sub-shell : they fork a process, and they are inefficient. Of course it works with several files, and this solution can be the fastest, or second to the fastest one.

这与sh和派生:ksh和bash一起工作。它不会创建任何子shell。(. .)和“美元……命令创建一个子shell:它们派生一个进程,并且效率低下。当然,它与几个文件一起工作,这个解决方案可以是最快的,也可以是最快的。

#8


5  

The question wasn't specific to Linux/Bash so I thought I would add the Powershell way - which treats wildcards different - you put it in the quotes like so below:

这个问题不是针对Linux/Bash的,所以我想我应该添加Powershell方式——它对通配符不一样——你把它放在引号里,如下所示:

If (Test-Path "./output/test-pdf-docx/Text-Book-Part-I*"){
  Remove-Item -force -v -path ./output/test-pdf-docx/*.pdf
  Remove-Item -force -v -path ./output/test-pdf-docx/*.docx
}

I think this is helpful because the concept of the original question covers "shells" in general not just Bash or Linux, and would apply to Powershell users with the same question too.

我认为这是有帮助的,因为原始问题的概念涵盖了“shell”,而不仅仅是Bash或Linux,而且也适用于具有同样问题的Powershell用户。

#9


3  

The bash code I use

我使用的bash代码。

if ls /syslog/*.log > /dev/null 2>&1; then 
   echo "Log files are present in /syslog/; 
fi

Thanks!

谢谢!

#10


3  

Strictly speaking, if you only want to print "Blah" here is the solution :

严格地说,如果你只想打印“Blah”这是解决方案:

find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 'BLAH' -quit

Here is another way :

这是另一种方法:

doesFirstFileExist(){
    test -e "$1"
}

if doesFirstFileExist xorg-x11-fonts*
then printf "BLAH"
fi

But I think the most optimal is as follow, because it won't try to sort file names :

但我认为最优的方法是遵循,因为它不会尝试对文件名进行排序:

if [ -z `find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 1 -quit` ]
then printf "BLAH"
fi

#11


2  

Here's a solution for your specific problem that doesn't require for loops or external commands like ls, find and the like.

这里有一个针对您的特定问题的解决方案,它不需要循环或像ls、find之类的外部命令。

if [ "$(echo xorg-x11-fonts*)" != "xorg-x11-fonts*" ]; then
    printf "BLAH"
fi

As you can see, it's just a tad more complicated than what you were hoping for, and relies on the fact that if the shell is not able to expand the glob, it means no files with that glob exist and echo will output the glob as is, which allows us to do a mere string comparison to check whether any of those files exist at all.

正如你所看到的,只是有点更复杂的比你所希望的,并依赖于这样一个事实,如果壳不能扩大水珠,水珠的存在意味着没有文件和回声将输出的水珠,这让我们做一个纯粹的字符串比较检查这些文件是否存在。

If we were to generalize the procedure, though, we should take into account the fact that files might contain spaces within their names and/or paths and that the glob char could rightfully expand to nothing (in your example, that would be the case of a file whose name is exactly xorg-x11-fonts).

如果我们要推广的过程,我们应该考虑到这一事实文件可能包含空间在他们的名字和/或路径,水珠char什么都理所当然地扩展到(在你的例子中,这将是一个文件的名字正是xorg-x11-fonts)。

This could be achieved by the following function, in bash.

这可以通过以下函数在bash中实现。

function doesAnyFileExist {
   local arg="$*"
   local files=($arg)
   [ ${#files[@]} -gt 1 ] || [ ${#files[@]} -eq 1 ] && [ -e "${files[0]}" ]
}

Going back to your example, it could be invoked like this.

回到您的示例,可以像这样调用它。

if doesAnyFileExist "xorg-x11-fonts*"; then
    printf "BLAH"
fi

Glob expansion should happen within the function itself for it to work properly, that's why I put the argument in quotes and that's what the first line in the function body is there for: so that any multiple arguments (which could be the result of a glob expansion outside the function, as well as a spurious parameter) would be coalesced into one. Another approach could be to raise an error if there's more than one argument, yet another could be to ignore all but the 1st argument.

水珠扩张应该发生在函数本身的正常工作,这就是为什么我把论点放在引号里,这就是第一行的函数体有:所以,任何多个参数(这可能是一团扩张的结果以外的功能,以及一个寄生参数)将合并成一个。另一种方法可能是,如果存在不止一个参数,则会引发错误,而另一个方法可能是忽略第一个参数。

The second line in the function body sets the files var to an array constituted by all the file names that the glob expanded to, one for each array element. It's fine if the file names contain spaces, each array element will contain the names as is, including the spaces.

函数体中的第二行将文件var设置为由glob扩展到的所有文件名组成的数组,每个数组元素对应一个数组。如果文件名包含空格,那么每个数组元素都会包含名称,包括空格。

The third line in the function body does two things:

函数体中的第三行做两件事:

  1. It first checks whether there's more than one element in the array. If so, it means the glob surely got expanded to something (due to what we did on the 1st line), which in turn implies that at least one file matching the glob exist, which is all we wanted to know.

    它首先检查数组中是否有多个元素。如果是这样,这意味着glob肯定会扩展到某些东西(由于我们在第一行中所做的事情),而这又意味着至少有一个文件与glob相匹配,这就是我们想要知道的。

  2. If at step 1. we discovered that we got less than 2 elements in the array, then we check whether we got one and if so we check whether that one exist, the usual way. We need to do this extra check in order to account for function arguments without glob chars, in which case the array contains only one, unexpanded, element.

    如果在步骤1。我们发现数组中有小于2个元素,然后我们检查是否有一个,如果这样,我们检查是否存在,通常的方式。我们需要做这个额外的检查,以解释没有glob chars的函数参数,在这种情况下,数组只包含一个未展开的元素。

#12


1  

I use this:

我用这个:

filescount=`ls xorg-x11-fonts* | awk 'END { print NR }'`  
if [ $filescount -gt 0 ]; then  
    blah  
fi

#13


1  

IMHO it's better to use find always when testing for files, globs or directories. The stumbling block in doing so is find's exit status: 0 if all paths were traversed successfully, >0 otherwise. The expression you passed to find creates no echo in its exit code.

在测试文件、全局或目录时,最好使用find。这样做的绊脚石是find的退出状态:如果所有路径都成功遍历,则>0。您传递的表达式在其退出代码中没有创建echo。

The following example tests if a directory has entries:

下面的示例测试目录是否有条目:

$ mkdir A
$ touch A/b
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty'
not empty

When A has no files grep fails:

当A没有文件grep失败:

$ rm A/b
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . || echo 'empty'
empty

When A does not exist grep fails again because find only prints to stderr:

当A不存在时,grep再次失败,因为只找到stderr的输出:

$ rmdir A
$ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty' || echo 'empty'
find: 'A': No such file or directory
empty

Replace -not -empty by any other find expression, but be careful if you -exec a command that prints to stdout. You may want to grep for a more specific expression in such cases.

用任何其他的查找表达式替换-not -empty,但是要小心,如果你-exec命令打印到stdout。在这种情况下,您可能需要grep以获得更具体的表达式。

This approach works nicely in shell scripts. The originally question was to look for the glob xorg-x11-fonts*:

这种方法在shell脚本中很好地工作。最初的问题是寻找glob xorg-x11字体*:

if find -maxdepth 0 -name 'xorg-x11-fonts*' -print | head -n1 | grep -q .
then
    : the glob matched
else
    : ...not
fi

Note that the else-branched is reached if xorg-x11-fonts* had not matched, or find encountered an error. To distinguish the case use $?.

注意,如果xorg-x11-font *没有匹配,或者发现遇到错误,则会到达else-branched。区分这个案例使用$?。

#14


1  

if [ `ls path1/* path2/* 2> /dev/null | wc -l` -ne 0 ]; then echo ok; else echo no; fi

#15


0  

Try this

试试这个

fileTarget="xorg-x11-fonts*"

filesFound=$(ls $fileTarget)  # 2014-04-03 edit 2: removed dbl-qts around $(...)

edit 2014-04-03 (removed dbl-quotes and added test file 'Charlie 22.html' (2 spaces)

编辑2014-04-03(删除dbl-quotes并添加测试文件“Charlie 22”。html的(2个空间)

case ${filesFound} in
  "" ) printf "NO files found for target=${fileTarget}\n" ;;
   * ) printf "FileTarget Files found=${filesFound}\n" ;;
esac 

Test

测试

fileTarget="*.html"  # where I have some html docs in the current dir

FileTarget Files found=Baby21.html
baby22.html
charlie  22.html
charlie21.html
charlie22.html
charlie23.html

fileTarget="xorg-x11-fonts*"

NO files found for target=xorg-x11-fonts*

Note that this only works in the current directory, or where the var fileTarget includes the path you are want to inspect.

注意,这只能在当前目录中工作,或者var文件目标包含您要检查的路径。

#16


0  

If there is a huge amount of files on a network folder using the wildcard is questionable (speed, or command line arguments overflow).

如果使用通配符的网络文件夹上有大量的文件是可疑的(速度,或者命令行参数溢出)。

I ended up with:

我结束了:

if [ -n "$(find somedir/that_may_not_exist_yet -maxdepth 1 -name \*.ext -print -quit)" ] ; then
  echo Such file exists
fi

#17


0  

You can also cut other files out

你也可以删除其他文件。

if [ -e $( echo $1 | cut -d" " -f1 ) ] ; then
   ...
fi

#18


0  

Using new fancy shmancy features in ksh, bash, and zsh shells (this example doesn't handle spaces in filenames):

在ksh、bash和zsh shell中使用新的花哨的shmancy特性(这个示例不处理文件名中的空格):

# Declare a regular array (-A will declare an associative array. Kewl!)
declare -a myarray=( /mydir/tmp*.txt )
array_length=${#myarray[@]}

# Not found if the 1st element of the array is the unexpanded string
# (ie, if it contains a "*")
if [[ ${myarray[0]} =~ [*] ]] ; then
   echo "No files not found"
elif [ $array_length -eq 1 ] ; then
   echo "File was found"
else
   echo "Files were found"
fi

for myfile in ${myarray[@]}
do
  echo "$myfile"
done

Yes, this does smell like Perl. Glad I didn't step in it ;)

是的,这闻起来像Perl。很高兴我没有踩到它。

#19


0  

Found a couple of neat solutions worth sharing. The first still suffers from "this will break if there's too many matches" problem:

找到了一些值得分享的简洁的解决方案。第一个问题仍然是“如果有太多的匹配”问题,“这将会中断”:

pat="yourpattern*" matches=($pat) ; [[ "$matches" != "$pat" ]] && echo "found"

(Recall that if you use an array without the [ ] syntax, you get the first element of the array.)

(回想一下,如果使用一个没有语法的数组,就会得到数组的第一个元素)。

If you have "shopt -s nullglob" in your script, you could simply do:

如果你的脚本中有“shopt -s nullglob”,你可以简单地做:

matches=(yourpattern*) ; [[ "$matches" ]] && echo "found"

Now, if it's possible to have a ton of files in a directory, you're pretty well much stuck with using find:

现在,如果有可能在一个目录中有大量的文件,那么你就很容易被发现:

find /path/to/dir -maxdepth 1 -type f -name 'yourpattern*' | grep -q '.' && echo 'found'

#20


-1  

How about

如何

if ls -l  | grep -q 'xorg-x11-fonts.*' # grep needs a regex, not a shell glob
then
     # do something
else
     # do something else
fi 

#21


-14  

man test

人测试

if [ -e file ]; then
...  
fi

will work for dir\file.

将为dir \文件工作。

regards

问候