这个问题在这里已有答案:
我正在尝试检查文件是否存在,但是使用通配符。这是我的例子:
if [ -f "xorg-x11-fonts*" ]; then
printf "BLAH"
fi
我也尝试过没有双引号。
最简单的应该是依赖ls
返回值(当文件不存在时返回非零值):
if ls /path/to/your/files* 1> /dev/null 2>&1; then
echo "files do exist"
else
echo "files do not exist"
fi
我重定向了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
这与@ grok12的答案非常相似,但它避免了整个列表中不必要的迭代。
我使用的bash代码
if ls /syslog/*.log > /dev/null 2>&1; then
echo "Log files are present in /syslog/;
fi
谢谢!
这是针对您的特定问题的解决方案,不需要for
循环或外部命令,如ls
,find
等。
if [ "$(echo xorg-x11-fonts*)" != "xorg-x11-fonts*" ]; then
printf "BLAH"
fi
正如你所看到的,它只是比你希望的更复杂,并且依赖于如果shell不能扩展glob的事实,这意味着没有具有该glob的文件存在而且echo
将输出glob作为是,它允许我们进行单纯的字符串比较,以检查是否存在任何这些文件。
但是,如果我们要概括这个过程,我们应该考虑到这样一个事实,即文件可能在其名称和/或路径中包含空格,并且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的结果)函数外部的扩展以及虚假参数将合并为一个。如果有多个参数,另一种方法可能是引发错误,而另一种方法可能是忽略除第一个参数之外的所有参数。
函数体中的第二行将files
var设置为由glob扩展到的所有文件名构成的数组,每个数组元素对应一个。如果文件名包含空格,则每个数组元素都包含名称,包括空格。
函数体中的第三行做了两件事:
我用这个:
filescount=`ls xorg-x11-fonts* | awk 'END { print NR }'`
if [ $filescount -gt 0 ]; then
blah
fi
恕我直言,最好在测试文件,globs或目录时使用find
。这样做的绊脚石是find
的退出状态:如果所有路径都成功遍历则为0,否则为> 0。传递给find
的表达式在其退出代码中不会创建回显。
以下示例测试目录是否包含条目:
$ 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
用任何其他-not -empty
表达式替换find
,但如果你-exec
打印到stdout的命令,请小心。在这种情况下,您可能希望grep寻找更具体的表达式。
这种方法在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*
没有匹配,则达到else分支,或者find
遇到错误。要区分案件使用$?
。
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-quotes并添加了测试文件'Charlie 22.html'(2个空格)
case ${filesFound} in
"" ) printf "NO files found for target=${fileTarget}\n" ;;
* ) printf "FileTarget Files found=${filesFound}\n" ;;
esac
测试
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
包含您要检查的路径。
怎么样
if ls -l | grep -q 'xorg-x11-fonts.*' # grep needs a regex, not a shell glob
then
# do something
else
# do something else
fi
如果使用通配符的网络文件夹中存在大量文件,则可疑(速度或命令行参数溢出)。
我结束了:
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
...
fi
在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
是的,这确实闻起来像Perl。很高兴我没有介入它;)
如果您的shell具有nullglob选项并且已打开,则将完全从命令行中删除不匹配任何文件的通配符模式。这将使ls看不到路径名参数,列出当前目录的内容并成功,这是错误的。 GNU stat,如果没有参数或命名不存在的文件的参数,总是会失败,会更强大。此外,&>重定向运算符是bashism.
if stat --printf='' /path/to/your/files* 2>/dev/null
then
echo found
else
echo not found
fi
更好的是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
非GNU版本的find可能没有这里使用的-maxdepth选项,只能搜索/ dir / to / search而不是整个目录树。
找到了一些值得分享的简洁解决方案。第一个仍然受到“如果有太多匹配问题就会破坏”的问题:
pat="yourpattern*" matches=($pat) ; [[ "$matches" != "$pat" ]] && echo "found"
(回想一下,如果你使用没有[ ]
语法的数组,你会得到数组的第一个元素。)
如果您的脚本中有“shopt -s nullglob”,则可以执行以下操作:
matches=(yourpattern*) ; [[ "$matches" ]] && echo "found"
现在,如果目录中可能有大量文件,那么使用find会非常困难:
find /path/to/dir -maxdepth 1 -type f -name 'yourpattern*' | grep -q '.' && echo 'found'
男人测试
if [ -e file ]; then
...
fi
将适用于dir \ file。
问候
这是我的答案 -
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
这将适用于多个文件和文件名中的空格。
您可以执行以下操作:
set -- xorg-x11-fonts*
if [ -f "$1" ]; then
printf "BLAH"
fi
这适用于sh和derivates:ksh和bash。它不会创建任何子shell。 $(..)和`...`命令创建一个子shell:它们分叉一个进程,它们效率低下。当然它适用于多个文件,这个解决方案可以是最快的,也可以是最快的解决方案。
当没有匹配时它也可以工作。没有必要使用nullglob作为其中一个comentatators说。 $ 1将包含原始测试名称,因此测试-f $ 1将不会成功,因为$ 1文件不存在。
更新:
好的,现在我肯定有解决方案:
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
这个问题并不是特定于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
}
我认为这很有用,因为原始问题的概念通常涵盖“shell”,而不仅仅是Bash或Linux,并且也适用于具有相同问题的Powershell用户。
严格来说,如果你只想打印“Blah”,这里就是解决方案:
find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 'BLAH' -quit
这是另一种方式:
doesFirstFileExist(){
test -e "$1"
}
if doesFirstFileExist xorg-x11-fonts*
then printf "BLAH"
fi
但我认为最优化的是如下,因为它不会尝试对文件名进行排序:
if [ -z `find . -maxdepth 1 -name 'xorg-x11-fonts*' -printf 1 -quit` ]
then printf "BLAH"
fi