Test whether a glob has any matches in bash
如果我想检查是否存在单个文件,我可以使用
假设我有一个glob,我想知道是否存在任何名称与glob匹配的文件。glob可以匹配0个文件(在这种情况下,我不需要做任何事情),或者它可以匹配1个或多个文件(在这种情况下,我需要做一些事情)。如何测试一个球是否有任何匹配项?(我不在乎有多少个匹配项,如果我能用一个
(如果glob匹配多个文件,则
事实上这是一nullglob壳的bashism选项。
为避免繁琐的需要保存和恢复状态的nullglob,我只把它填满,扩大在全球的内幕:
1 2 3 4 5 6 | if test -n"$(shopt -s nullglob; echo glob*)" then echo found else echo not found fi |
为更好的可移植性和更灵活的通配符查找,使用:
1 2 3 4 5 6 | if test -n"$(find . -maxdepth 1 -name 'glob*' -print -quit)" then echo found else echo not found fi |
显的行为是用于印刷的退出,而不是默认的"打印"这样的隐式的动作将退出尽快找到匹配的文件,它的第一搜索准则。在许多文件的运行更快的比赛,这应该不太
如果找到感觉。样和数量匹配的文件可能是小的,使用的统计:
1 2 3 4 5 6 | if stat -t glob* >/dev/null 2>&1 then echo found else echo not found fi |
Bash specific solution:
1 | compgen -G"<glob-pattern>" |
逃亡的模式或它会对比赛有预扩增。
退出状态是:
- 1是在比赛。
- 如果一个或更多的比赛。"
更新:使用要求的例子。
1 2 3 | if compgen -G"/tmp/someFiles*"> /dev/null; then echo"Some files exist." fi |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/env bash # If it is set, then an unmatched glob is swept away entirely -- # replaced with a set of zero words -- # instead of remaining in place as a single word. shopt -s nullglob M=(*px) if ["${#M[*]}" -ge 1 ]; then echo"${#M[*]} matches." else echo"No such files." fi |
我喜欢
1 2 3 4 5 6 7 8 9 | exists() { [ -e"$1" ] } if exists glob*; then echo found else echo not found fi |
这是一个可读的和有效的(除非有这巨大的数量的文件)。的主要缺点是,它是更大的比长的文字,我有时感觉到龙compelled添加评论。如果有一个匹配,
编辑:有可能是假阳性,见评论
我有一个解决方案:一个是美国
1 | if ["$(echo glob*)" != 'glob*' ] |
本厂是nicely我。有一些案件的一角吗?
如果你有,你可以使用这个globfail集疯狂(你真的不应该)
1 2 | shopt -s failglob # exit if * does not match ( : * ) && echo 0 || echo 1 |
或
1 | q=( * ) && echo 0 || echo 1 |
myyn到简化的基于点的答案,他的理念:
1 2 3 4 5 6 | M=(*py) if [ -e ${M[0]} ]; then echo Found else echo Not Found fi |
基于flabdablet的答案,它看起来像是我easiest(并不一定是最快的),只是为了找到本身的使用,而离开地球展开在线壳样:
1 | find /some/{p,long-p}ath/with/*globs* -quit &> /dev/null && echo"MATCH" |
或在
1 2 3 4 5 | if find $yourGlob -quit &> /dev/null; then echo"MATCH" else echo"NOT-FOUND" fi |
我没有看到这个回答,所以我想我把它有。
1 2 | set -- glob* [ -f"$1" ] && echo"found $@" |
这似乎令人厌恶的工作。
1 2 3 4 5 6 7 | #!/usr/bin/env bash shopt -s nullglob if ["`echo *py`" !="" ]; then echo"Glob matched" else echo"Glob did not match" fi |
它可能需要打,不显示。
本厂nullglob期权的原因。因为在一个空字符串来评价,如果有在比赛中。因此,任何非空输出命令是从回波信号生成表示匹配的东西。
在派对上,你可以去到一个数组的函数;如果不匹配,您将输入数组包含单是不是对应到一个现有的文件。
1 2 3 4 5 6 7 8 9 | #!/bin/bash shellglob='*.sh' scripts=($shellglob) if [ -e"${scripts[0]}" ] then stat"${scripts[@]}" fi |
注意:如果你有一
1 | if ["${scripts[*]}" ] && [ -e"${scripts[0]}" ] |
这种方法的优势是,然后你有你的工作列表的文件要用的,而不是由一对重复的操作。
1 2 3 4 | set -- glob* if [ -f"$1" ]; then echo"It matched" fi |
解释
如果没有与
这适用于sh和派生词:ksh和bash。它不会创建任何子shell。
] [
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/bash set nullglob touch /tmp/foo1 /tmp/foo2 /tmp/foo3 FOUND=0 for FILE in /tmp/foo* do FOUND=$((${FOUND} + 1)) done if [ ${FOUND} -gt 0 ]; then echo"I found ${FOUND} matches" else echo"No matches found" fi |
1 2 3 4 5 | if ls -d $glob > /dev/null 2>&1; then echo Found. else echo Not found. fi |
请注意,这可以产生超的球队比赛,如果有很多文件或访问是慢的。
不是最有效的解决方案(如果有)的文件在目录中,它可能是slowish),但它的简单,容易阅读,也有更多的优点,比普通攻击是强大的regexes glob模式。
1 | (ls glob* &>/dev/null && echo Files found) || echo No file found |