日期:2014-05-16  浏览次数:20713 次

在Linux下怎么用Bash判断是否存在某种模式的文件名

问:在Linux下怎么用Bash判断是否存在某种模式的文件名?

比如,用脚本判断是否有 *_codec.* 形式的文件名,或者有 *.gif 形式的文件名。

?

答:

方法一:

[ "$(ls *.gif 2>/dev/null)" ] && echo "*.gif exists" || echo "*.gif not exists"

方法二:

exists_pattern_files(){
??? [ -e "$1" ]
}

exists_pattern_files *.gif && echo "*.gif exists" || echo "*.gif not exists"

?

探索过程:

?

用 test -e file 或 [ -e file ] 只能判断单个确定名称的文件,如果是通配符模式指定的文件名,这种方式就不凑效了。

有三种情况需要考虑到:

(1)没有匹配此模式的文件;

(2)刚好有一个匹配此模式的文件;

(3)有多于一个匹配此模式的文件;

?

下面以 *.gif 模式来测试:

(1)没有匹配此模式的文件;

[root@liunx0918 tmp0]# ls *.gif
ls: *.gif: 没有那个文件或目录
[root@liunx0918 tmp0]# [ -e *.gif ] && echo "*.gif exists" || echo "*.gif not exists"
*.gif not exists
[root@liunx0918 tmp0]#

(2)刚好有一个匹配此模式的文件;

[root@liunx0918 tmp0]# touch 1.gif
[root@liunx0918 tmp0]# ls *.gif
1.gif
[root@liunx0918 tmp0]# [ -e *.gif ] && echo "*.gif exists" || echo "*.gif not exists"
*.gif exists
[root@liunx0918 tmp0]#

(3)有多于一个匹配此模式的文件;

[root@liunx0918 tmp0]# touch 2.gif
[root@liunx0918 tmp0]# ls *.gif
1.gif? 2.gif
[root@liunx0918 tmp0]# [ -e *.gif ] && echo "*.gif exists" || echo "*.gif not exists"
-bash: [: 1.gif: binary operator expected
*.gif not exists
[root@liunx0918 tmp0]#

?

前面两种情况,还可以判断,第三种情况脚本就会报错,谁又能保证匹配的文件不会多于一个呢?

?

首先想到:可以用 ls 命令先列出该模式文件的输出进行判断。如下所示:

(1)没有匹配此模式的文件;

[root@liunx0918 tmp1]# ls *.gif
ls: *.gif: 没有那个文件或目录
[root@liunx0918 tmp1]# [ "$(ls *.gif)" ] && echo "*.gif exists" || echo "*.gif not exists"
ls: *.gif: 没有那个文件或目录
*.gif not exists
[root@liunx0918 tmp1]#

注意上面标记为红色的内容,其实脚本中不希望看到这个信息,这个信息是输出在标准错误输出的,用下面的方法可以

[root@liunx0918 tmp1]# [ "$(ls *.gif 2>/dev/null)" ] && echo "*.gif exists" || echo "*.gif not exists"
*.gif not exists
[root@liunx0918 tmp1]#

(2)刚好有一个匹配此模式的文件;

[root@liunx0918 tmp1]# touch 1.gif
[root@liunx0918 tmp1]# ls *.gif
1.gif
[root@liunx0918 tmp1]# [ "$(ls *.gif 2>/dev/null)" ] && echo "*.gif exists" || echo "*.gif not exists"
*.gif exists
[root@liunx0918 tmp1]#

(3)有多于一个匹配此模式的文件;

[root@liunx0918 tmp1]# touch 2.gif
[root@liunx0918 tmp1]# ls *.gif
1.gif? 2.gif
[root@liunx0918 tmp1]# [ "$(ls *.gif 2>/dev/null)" ] && echo "*.gif exists" || echo "*.gif not exists"
*.gif exists
[root@liunx0918 tmp1]#

?

忽然灵光一闪,既然可以通过ls列举文件的方式来进行,其实Bash本身就支持文件名通配符展开,不妨来写个简单的函数

exists_pattern_files(){
    [ -e "$1" ]
}
?

[root@liunx0918 tmp2]# exists_pattern_files(){
> [ -e "$1" ]
> }