如果我要检查单个文件的存在,我可以测试使用它的test -e filename
或[ -e filename ]
。
假如我有水珠,我想知道的任何文件是否存在,其名称与水珠。 水珠可以匹配0文件(在这种情况下,我需要做什么),也可以搭配1个或多个文件(在这种情况下,我需要做的事情)。 如何测试一个水珠是否有比赛吗? (我不在乎有多少场比赛也有,这将是最好的,如果我能做到这一点有一个if
语句,并没有循环(只是因为我发现,最可读的)。
( test -e glob*
如果水珠匹配多个文件失败。)
Answer 1:
猛砸具体的解决方案:
compgen -G "<glob-pattern>"
逃脱模式,或者会得到预扩展到匹配。
退出状态是:
stdout
是匹配的水珠文件的列表。
我认为这是简洁和减少潜在的副作用而言是最好的选择。
UPDATE:实施例的使用请求。
if compgen -G "/tmp/someFiles*" > /dev/null; then
echo "Some files exist."
fi
Answer 2:
该壳了nullglob选择的确是一个bashism。
为了避免保存和状态了nullglob的恢复需要一个繁琐的,我只设置一个可扩展的水珠子shell里:
if test -n "$(shopt -s nullglob; echo glob*)"
then
echo found
else
echo not found
fi
为了更好的便携性和更灵活的匹配,一种使用发现:
if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
echo found
else
echo not found
fi
明确-print -QUIT动作用于发现 ,而不是默认隐含-print操作,以便发现它找到的第一个文件符合搜索条件会尽快退出。 其中许多文件匹配,这应该跑得比快得多echo glob*
或ls glob*
,同时也避免了overstuffing扩展命令行(有些炮弹具有4K长度限制)的可能性。
如果找到感觉就像矫枉过正和可能匹配文件的数量少,使用统计:
if stat -t glob* >/dev/null 2>&1
then
echo found
else
echo not found
fi
Answer 3:
#!/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
Answer 4:
我喜欢
exists() {
[ -e "$1" ]
}
if exists glob*; then
echo found
else
echo not found
fi
这是可读可有效(除非有文件数量巨大)。
主要缺点是,它是更加微妙比它看起来,我有时觉得有必要增加一个长注释。
如果有一场比赛, "glob*"
被shell展开,所有比赛被传递到exists()
检查第一个而忽略其他。
如果没有匹配, "glob*"
传递给exists()
并没有发现任何存在那里。
编辑:有可能是假阳性,看评论
Answer 5:
测试-e有不幸的警告,它认为破符号链接不存在。 所以,你可能要检查这些,太。
function globexists {
test -e "$1" -o -L "$1"
}
if globexists glob*; then
echo found
else
echo not found
fi
Answer 6:
如果你有globfail设置,你可以使用这个疯狂的(你真的不应该)
shopt -s failglob # exit if * does not match
( : * ) && echo 0 || echo 1
要么
q=( * ) && echo 0 || echo 1
Answer 7:
我还有另一种解决方案:
if [ "$(echo glob*)" != 'glob*' ]
这很好地工作对我来说。 是否有一些角落情况下,我错过?
Answer 8:
在一定程度上简化MYYN的回答,根据他的想法:
M=(*py)
if [ -e ${M[0]} ]; then
echo Found
else
echo Not Found
fi
Answer 9:
基于flabdablet的回答 ,对我来说,它看起来像最简单的(不一定是最快的)就是使用发现自己,而留下水珠扩张的外壳,如:
find /some/{p,long-p}ath/with/*globs* -quit &> /dev/null && echo "MATCH"
或者if
这样的:
if find $yourGlob -quit &> /dev/null; then
echo "MATCH"
else
echo "NOT-FOUND"
fi
Answer 10:
这憎恶似乎工作:
#!/usr/bin/env bash
shopt -s nullglob
if [ "`echo *py`" != "" ]; then
echo "Glob matched"
else
echo "Glob did not match"
fi
它可能需要bash中,没有SH。
这工作,因为nullglob选项,将会导致水珠,以评估为空字符串,如果没有匹配。 因此,从回波命令任何非空输出表明水珠匹配的东西。
Answer 11:
我没有看到这个答案,所以我想我把它放在那里:
set -- glob*
[ -f "$1" ] && echo "found $@"
Answer 12:
在bash中,你可以使用通配到一个数组; 如果水珠不匹配,你的阵列将包含不符合现有文件的一个条目:
#!/bin/bash
shellglob='*.sh'
scripts=($shellglob)
if [ -e "${scripts[0]}" ]
then stat "${scripts[@]}"
fi
注意:如果你有nullglob
集, scripts
将是一个空数组,你应该测试[ "${scripts[*]}" ]
或[ "${#scripts[*]}" != 0 ]
代替。 如果你正在写必须有或没有工作的图书馆nullglob
,你会想
if [ "${scripts[*]}" ] && [ -e "${scripts[0]}" ]
这种方法的好处是,你再有你想要的工作,而不是重复水珠操作的文件列表。
Answer 13:
if ls -d $glob > /dev/null 2>&1; then
echo Found.
else
echo Not found.
fi
请注意,这可能是很长的时间cosuming如果有很多的比赛或文件访问速度很慢。
Answer 14:
#!/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
Answer 15:
[ ls glob* 2>/dev/null | head -n 1
ls glob* 2>/dev/null | head -n 1
]回波真&&
Answer 16:
set -- glob*
if [ -f "$1" ]; then
echo "It matched"
fi
说明
当没有一个匹配glob*
,那么$1
将包含'glob*'
。 测试-f "$1"
,因为该不会是真的glob*
文件不存在。
为什么这是不是更好的选择
这适用于sh和衍生物:KSH和bash。 它不会产生任何子shell。 $(..)
和`...`
命令创建一个子shell; 它们派生进程,因此,比这溶液慢。
Answer 17:
(ls glob* &>/dev/null && echo Files found) || echo No file found
Answer 18:
ls | grep -q "glob.*"
这不是最有效的解决方案(如果有一吨的目录可能是slowish文件),但其实很简单,易于阅读,还具有的优点是,正则表达式是比普通的bash glob模式更加强大。
文章来源: Test whether a glob has any matches in bash