Linux判断通配符⽂件存在,在shell脚本中检查⽂件是否存在通
配符
最简单的应该是依靠ls返回值(当⽂件不存在时它会返回⾮零值):
if ls /path/to/your/files* 1> /dev/null 2>&1; then echo "files do exist" else echo "files do not exist" fi
我redirectls输出,使其完全沉默。
编辑:由于这个答案已经得到了⼀些关注(和评论⾮常有⽤的批评评论),这⾥是⼀个优化,也依赖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
这与@ grok12的答案⾮常相似,但它避免了整个列表中不必要的迭代。
如果你的shell有⼀个nullglob选项并且它被打开,那么⼀个不匹配⽂件的通配符模式将被从命令⾏中删除。 这将使ls看不到path名参数,列出当前⽬录的内容并成功,这是错误的。 GNU stat ,如果没有给定参数或命名⼀个不存在⽂件的参数,它总是会失败,这样会更健壮。另外,&>redirect操作符是⼀个双击操作。
if stat --printf='' /path/to/your/files* 2>/dev/null then echo found else echo not found fi
更好的是GNU find ,它可以在内部处理通配符search,并在find⼀个匹配的⽂件时⽴即退出,⽽不是浪费时间处理由shell扩展的可能庞⼤的列表。 这也避免了shell可能溢出其命令⾏缓冲区的风险。
if test -n "$(find /dir/to/search -maxdepth 1 -name 'files*' -print -quit)" then echo found else echo not found fi
find的⾮GNU版本可能没有这⾥使⽤的-maxdepth选项来查只search/ dir / to / search,⽽不是整个⽬录树。
这是我的答案 –
files=(xorg-x11-fonts*) if [ -e "${files[0]}" ]; then printf "BLAH" fi
for i in xorg-x11-fonts*; do if [ -f "$i" ]; then printf "BLAH"; fi done
这将使⽤多个⽂件和⽂件名中的空格。
更新:
好吧,现在我肯定有解决办法:
files=$(ls xorg-x11-fonts* 2> /dev/null | wc -l) if [ "$files" != "0" ] then echo "Exists" else echo "None found." fi > Exists
也许这会帮助别⼈:
if [ "`echo xorg-x11-fonts*`" != "xorg-x11-fonts*" ]; then printf "BLAH" fi
您可以执⾏以下操作:
set -- xorg-x11-fonts* if [ -f "$1" ]; then printf "BLAH" fi
这适⽤于sh和派⽣:ksh和bash。 它不创build任何⼦shell。 $(..)和`…`命令创build⼀个⼦shell:他们分叉进程,效率低下。
这个问题不是特定于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 }
我认为这很有帮助,因为原始问题的概念通常不仅包括Bash或Linux,⽽且也包含相同问题的Powershell⽤户。
我使⽤的bash代码
if ls /syslog/*.log > /dev/null 2>&1; then echo "Log files are present in /syslog/; fi
谢谢!
严格来说,如果你只想打印“Blah”,这⾥的解决scheme是:
find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 'BLAH' -quit
这是另⼀种⽅式:
doesFirstFileExist(){ test -e "$1" } if doesFirstFileExist xorg-x11-fonts* then printf "BLAH" fi
但我认为最优化的是如下,因为它不会尝试对⽂件名进⾏sorting:
if [ -z `find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 1 -quit` ] then printf "BLAH" fi
这是针对您的特定问题的解决scheme,不需要循环或外部命令(如ls , find等)。
if [ "$(echo xorg-x11-fonts*)" != "xorg-x11-fonts*" ]; then printf "BLAH" fi
正如你所看到的,它⽐你想要的要复杂得多,⽽且依赖于如果shell不能扩展glob,那就意味着没有那个glob的⽂件存在,并且echo会输出glob 是 ,它允许我们做⼀个纯粹的string⽐较来检查是否有任何这些⽂件存在。
但是,如果我们要推⼴这个过程 ,我们应该考虑到这样⼀个事实,即⽂件可能在其名称和/或path中包含空格 ,并且glob char可以正确地展开为空(在你的例⼦中,这将是⼀个名字正好是 xorg-x11-fonts的⽂件)。
这可以通过以下函数在bash中实现 。
function doesAnyFileExist { local arg="$*" local files=($arg) [ ${#files[@]} -gt 1 ] || [ ${#files[@]} -eq 1 ] && [ -e "${files[0]}" ] }
回到你的例⼦,可以像这样调⽤它。
if doesAnyFileExist "xorg-x11-fonts*"; then printf "BLAH" fi
Glob扩展应该在函数本⾝内部发⽣,以使其正常⼯作,这就是为什么我把引数放在引号中,这就是函数体中的第⼀⾏:因此任何多个参数(可能是glob的结果函数外的扩展以及伪参数)将被合并为⼀个。 如果有多个参数,另⼀种⽅法可能是提出错误,另⼀种⽅法是忽略除第⼀个参数之外的所有错误。
函数体中的第⼆⾏将files var设置为由glob扩展到的所有⽂件名构成的数组 ,每个数组元素对应⼀个⽂件名。 如果⽂件名包含空格 , 那就好了 ,每个数组元素将包含名称(包括空格)。
函数体中的第三⾏做了两件事:
它⾸先检查数组中是否有多个元素。 如果是这样,这意味着glob 肯定会扩展到某些东西(由于我们在第⼀⾏做了什么),这⼜意味着⾄less 有⼀个匹配glob的⽂件存在,这是我们想知道的。
如果在步骤1,我们发现我们得到的数组less于2个,那么我们检查是否有⼀个,如果是的话,我们检
查是否存在,通常的⽅式。 我们需要进⾏额外的检查,以解释没有 glob字符的函数参数,在这种情况下,数组只包含⼀个未展开的元素。
我使⽤这个:
filescount=`ls xorg-x11-fonts* | awk 'END { print NR }'` if [ $filescount -gt 0 ]; then blah fi
恕我直⾔,最好总是在testing⽂件,球体或⽬录时使⽤find 。 这样做的绊脚⽯是find的退出状态:0,如果所有的path都成功遍历,否则> 0。 您传递给find的expression式在其退出代码中不会创build回显。
以下⽰例testing⽬录是否包含条⽬:
$ mkdir A $ touch A/b $ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . && echo 'not empty' not empty
当A没有⽂件时grep失败:
$ rm A/b $ find A -maxdepth 0 -not -empty -print | head -n1 | grep -q . || echo 'empty' empty
当A不存在时, grep再次失败,因为find只打印到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
⽤任何其他findexpression式replace-not -empty ,但要⼩⼼,如果你执⾏打印到标准输出的命令。 在这种情况下,您可能希望获得更具体的expression。
这种⽅法在shell脚本中很好地⼯作。 最初的问题是寻glob xorg-x11-fonts* :
if find -maxdepth 0 -name 'xorg-x11-fonts*' -print | head -n1 | grep -q . then : the glob matched else : ...not fi
请注意,如果xorg-x11-fonts*不匹配,或者find遇到错误,则会到达else分⽀。 区分使⽤$?的情况$? 。
if [ `ls path1/* path2/* 2> /dev/null | wc -l` -ne 0 ]; then echo ok; else echo no; fi
尝试这个
fileTarget="xorg-x11-fonts*" filesFound=$(ls $fileTarget) # 2014-04-03 edit 2: removed dbl-qts around $(...)
编辑2014-04-03(删除dbl引号并添加了testing⽂件“Charlie 22.html”(2个空格)
case ${filesFound} in "" ) printf "NO files found for target=${fileTarget}\n" ;; * ) printf "FileTarget Files
found=${filesFound}\n" ;; esac
testing
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*
请注意,这仅适⽤于当前⽬录,或者var fileTarget包含您要检查的path。
如果使⽤通配符的networking⽂件夹上有⼤量⽂件是有问题的(速度或命令⾏参数溢出)。
我结束了:
if [ -n "$(find somedir/that_may_not_exist_yet -maxdepth 1 -name \*.ext -print -quit)" ] ; then echo Such file exists fi
你也可以剪掉其他⽂件
if [ -e $( echo $1 | cut -d" " -f1 ) ] ; then ... filinux循环执行命令脚本
怎么样
if ls -l | grep -q 'xorg-x11-fonts.*' # grep needs a regex, not a shell glob then # do something else # do something else fi
⼈testing
if [ -e file ]; then ... fi
将⼯作dir \⽂件。
问候

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。