六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 43|回复: 0

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

[复制链接]

升级  79.6%

288

主题

288

主题

288

主题

进士

Rank: 4

积分
898
 楼主| 发表于 2013-2-4 13:30:23 | 显示全部楼层 |阅读模式
问:在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" ]
> }
注意,把文件名模式作为参数传递给此函数(不带任何引号),Bash就会自动展开文件模式,有多少个匹配的文件就会有多少个参数,而模式本身不会当做参数传递给函数;
如果没有匹配的文件名称,把模式本身传递给函数。而这个函数的实现部分相当简单,只需要对第一个参数指定的文件进行判断即可,为了保险起见,带上双引号。
(1)没有匹配此模式的文件;
[root@liunx0918 tmp2]# ls *.gif
ls: *.gif: 没有那个文件或目录
[root@liunx0918 tmp2]# exists_pattern_files *.gif && echo "*.gif exists" || echo "*.gif not exists"
*.gif not exists
(2)刚好有一个匹配此模式的文件;
[root@liunx0918 tmp2]# touch 1.gif
[root@liunx0918 tmp2]# ls *.gif
1.gif
[root@liunx0918 tmp2]# exists_pattern_files *.gif && echo "*.gif exists" || echo "*.gif not exists"
*.gif exists
(3)有多于一个匹配此模式的文件;
[root@liunx0918 tmp2]# touch 2.gif
[root@liunx0918 tmp2]# ls *.gif
1.gif  2.gif
[root@liunx0918 tmp2]# exists_pattern_files *.gif && echo "*.gif exists" || echo "*.gif not exists"
*.gif exists
[root@liunx0918 tmp2]#
 
本文链接:http://codingstandards.iteye.com/blog/1183303

 
下面贴一下我所需要的脚本内容。
对当前目录下各个子目录判断,如果子目录中包含*_codec.*形式的文件,就执行指定的动作。
 
实现一:
for d in *do        FILES=$(ls $d/*_codec.* 2>/dev/null)        if [ "$FILES" ]; then                #echo "$d" "[$FILES]"                (cd $d; make msg)        fidone 
实现二:
exists_pattern_files(){    [ -e "$1" ]}for d in *do        if exists_pattern_files $d/*_codec.*; then                #echo "$d" "[$FILES]"                (cd $d; make msg)        fidone
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表