Shell如何检查一个目录是否为空?(shell如何检查一个目录是否为空的)
off999 2024-11-14 16:52 34 浏览 0 评论
如何检查一个目录是否为空?如何检查是否存在任何 *.mpg 文件,或者计算有多少个这样的文件?
在 Bash 中,你可以通过使用 nullglob 和 dotglob 选项(这会改变 globbing 的行为),以及一个 array,安全而简便地计算文件数量:
# Bash
shopt -s nullglob dotglob
files=(*)
(( ${#files[*]} )) || echo 目录为空
shopt -u nullglob dotglob
当然,你可以使用任何你喜欢的 glob,而不仅仅是 。比如,.mpg 或者 /my/music/*.mpg 都可以正常工作。
请注意,你需要对目录拥有读取权限,否则它将始终显示为空。
一些人不喜欢 nullglob,因为没有匹配的 glob 会完全消失,这会让像 ls 这样的程序感到困惑。如果将 ls *.zip 错误地输入为 ls *.zpi,可能会导致显示所有文件(对于这种情况,考虑设置 failglob)。在子 shell 中设置 nullglob 可以避免意外地改变其余部分的 shell 设置,但代价是额外的 fork()。如果你想避免设置和取消设置 shell 选项,你可以将所有内容放入一个子 shell:
# Bash
if (shopt -s nullglob dotglob; f=(*); ((! ${#f[@]}))); then
echo "当前目录为空。"
fi
这种方法的另一个缺点(除了额外的 fork())是,当子 shell 退出时,数组会丢失。如果你计划稍后使用这些文件名,那么它们必须再次检索。
这两个示例都会扩展 glob 并将结果文件名存储到一个数组中,然后检查数组中元素的数量是否为 0。如果你实际上想要查看有多少个文件,只需打印数组的大小,而不是检查它是否为 0:
# Bash
shopt -s nullglob dotglob
files=(*)
echo "当前目录包含 ${#files[@]} 个文件。"
如果你不介意在数组中放入一个不存在的文件名(而不是一个空数组),你也可以避免使用 nullglob:
# Bash
shopt -s dotglob
files=(*)
if [[ -e ${files[0]} || -L ${files[0]} ]]; then
echo "当前目录不为空。它包含以下文件:"
printf '%s\n' "${files[@]}"
fi
如果目录中没有文件,则没有 nullglob,这个 glob 将被添加为数组中的唯一元素。由于 * 是一个有效的文件名,我们无法简单地检查数组是否包含一个字面上的 *。因此,我们检查数组中的内容是否作为文件存在。需要注意的是,-L 测试是必需的,因为 -e 如果第一个文件是一个 dangling symlink,将失败。
如果您不关心有多少匹配的文件,并且不想将结果存储在数组中,您可以使用Bash的compgen命令。不幸的是,由于一个bug,您需要使用一个技巧让其识别dotglob:
# Bash
if (shopt -s dotglob; : *; compgen -G '*' >/dev/null); then
echo "当前目录不为空。"
else
echo "当前目录为空。"
fi
或者您可以使用扩展的glob:
# Bash
# 可以通过为整个脚本启用extglob来避免子shell。
# 这样做是安全的。
if (shopt -s extglob; compgen -G '@(*|.[!.]*|..?*)' >/dev/null); then
echo "当前目录不为空。"
else
echo "当前目录为空。"
fi
您还可以使用failglob:
# Bash
if (shopt -s dotglob failglob; : ./*) 2>/dev/null; then
echo "当前目录不为空。"
else
echo "当前目录为空。"
fi
但是,请注意,如果您使用failglob,则需要子shell;下面的代码无法运行,因为failglob会引发一个shell错误,导致Bash停止运行当前命令(包括if命令,任何外部复合命令以及运行此代码的整个函数,如果它是函数的一部分),因此这仅适用于true的情况,else分支永远不会运行:
# 错误的代码!
shopt -s dotglob failglob
if { : ./*; } 2>/dev/null; then
echo "当前目录不为空。"
else
echo "当前目录为空。"
fi
如果您真的想避免使用子shell并且想要全局设置failglob,您可以使用命令eval来“捕获”shell错误,或者您可以编写一个间接展开glob的函数:
shopt -s dotglob failglob
if command eval ': ./*' 2>/dev/null; then
echo "当前目录不为空。"
else
echo "当前目录为空。"
fi
# 或者
shopt -s dotglob failglob
any_match () { local IFS=; { : "$@"; } 2>/dev/null; }
if any_match './*'; then
echo "当前目录不为空。"
else
echo "当前目录为空。"
fi
如果您的脚本需要在各种非Bash shell实现中运行,您可以尝试使用外部程序如Python、Perl或find;或者您可以尝试以下方法。请注意“magic 3 globs”^[1],因为POSIX没有dotglob选项。
# POSIX
# 这会破坏位置参数,所以确保您不需要它们。
set -- * .[!.]* ..?*
for f in "$@"; do
if test -e "$f" || test -L "$f"; then
echo "目录不为空"
break
fi
done
在这个阶段,位置参数已经加载了目录的内容,并且可以用于处理。
如果你只想计算文件数量:
# POSIX
n=0
for f in * .[!.]* ..?*; do
if test -e "$f" || test -L "$f"; then n=$((n+1)); fi
done
printf "共有 %d 个文件。\n" "$n"
在 Bourne shell 中,情况更糟糕,因为没有 test -e 或 test -L?:
# Bourne
# (当然,系统必须有 printf(1)。)
if test "`printf '%s %s %s' .* *`" = '. .. *' && test ! -f '*'
then
echo "目录为空"
fi
当然,如果 *? 存在于普通文件以外的其他内容(如目录或 FIFO),这种方法会失败。缺少 -e? 测试真的很痛苦。
这里还有另一种使用 find? 的解决方案:
# POSIX
# 打印每个文件的一个 `.` 并计算打印的字符数。
# 这个解决方案将递归。如果不想递归,请参见下面的内容。
n=$(find . -type f -exec printf %.0s. {} + | wc -m)
printf "共有 %d 个文件。\n" "$n"
如果你不希望递归,那么你需要告诉 find? 不要递归进入目录。这变得非常棘手和丑陋。GNU find? 有一个 -maxdepth? 选项来实现此功能。对于标准的 POSIX find?,你只能使用 -prune?。这留给读者作为练习。
永远不要尝试解析 ls? 的输出。即使是 ls -A? 的解决方案也可能会出错(例如,在 HP-UX 上,如果你是 root 用户,ls -A? 与非 root 用户的行为正好相反--不,我不能编造出这么愚蠢的东西)。
实际上,你可能希望完全避免直接的 *问题。通常人们想知道一个目录是否为空是因为他们想在其中的文件中进行一些操作等。要看到更大的问题。例如,这些基于 find? 的例子可能是一个合适的解决方案:
# Bourne / POSIX
find "$somedir" -type f -exec echo 发现意外的文件 {} \;
find "$somedir" -prune -empty -exec printf '%s 是空的。\n' {} \; # GNU/BSD
find "$somedir" -type d -empty -exec cp /my/configfile {} \; # GNU/BSD
最常见的情况是只需要像这样:
# Bourne / POSIX
for f in ./*.mpg; do
test -f "$f" || continue
mympgviewer "$f"
done
换句话说,提问者可能认为需要显式的空目录测试来避免出现错误消息,比如 mympgviewer: ./*.mpg: No such file or directory?,当实际上并不需要这样的测试。
对于类似 nullglob 的特性的支持是不一致的。在 ksh93 中,可以通过在模式前加上 ~(N)? 来实现每个模式的基础:
# ksh93
for f in ~(N)*; do
....
done
如果您觉得文章内容对你有一点帮助可以关注我,我在头条平台会持续分享更多实用的shell技巧和最佳实践,如果想系统的快速学习shell的各种高阶用法和生产环境避坑指南可以看看《shell脚本编程最佳实践》专栏,专栏里有更多的实用小技巧和脚本代码分享。
相关推荐
- 安全教育登录入口平台(安全教育登录入口平台官网)
-
122交通安全教育怎么登录:122交通网的注册方法是首先登录网址http://www.122.cn/,接着打开网页后,点击右上角的“个人登录”;其次进入邮箱注册,然后进入到注册页面,输入相关信息即可完...
- 大鱼吃小鱼经典版(大鱼吃小鱼经典版(经典版)官方版)
-
大鱼吃小鱼小鱼吃虾是于谦跟郭麒麟的《我的棒儿呢?》郭德纲说于思洋郭麒麟作诗的相声,最后郭麒麟做了一首,师傅躺在师母身上大鱼吃小鱼小鱼吃虾虾吃水水落石出师傅压师娘师娘压床床压地地动山摇。...
-
- 哪个软件可以免费pdf转ppt(免费的pdf转ppt软件哪个好)
-
要想将ppt免费转换为pdf的话,我们建议大家可以下一个那个wps,如果你是会员的话,可以注册为会员,这样的话,在wps里面的话,就可以免费将ppt呢转换为pdfpdf之后呢,我们就可以直接使用,不需要去直接不需要去另外保存,为什么格式转...
-
2026-02-04 09:03 off999
- 电信宽带测速官网入口(电信宽带测速官网入口app)
-
这个网站看看http://www.swok.cn/pcindex.jsp1.登录中国电信网上营业厅,宽带光纤,贴心服务,宽带测速2.下载第三方软件,如360等。进行在线测速进行宽带测速时,尽...
- 植物大战僵尸95版手机下载(植物大战僵尸95 版下载)
-
1可以在应用商店或者游戏平台上下载植物大战僵尸95版手机游戏。2下载教程:打开应用商店或者游戏平台,搜索“植物大战僵尸95版”,找到游戏后点击下载按钮,等待下载完成即可安装并开始游戏。3注意:确...
- 免费下载ppt成品的网站(ppt成品免费下载的网站有哪些)
-
1、Chuangkit(chuangkit.com)直达地址:chuangkit.com2、Woodo幻灯片(woodo.cn)直达链接:woodo.cn3、OfficePlus(officeplu...
- 2025世界杯赛程表(2025世界杯在哪个国家)
-
2022年卡塔尔世界杯赛程公布,全部比赛在卡塔尔境内8座球场举行,2022年,决赛阶段球队全部确定。揭幕战于当地时间11月20日19时进行,由东道主卡塔尔对阵厄瓜多尔,决赛于当地时间12月18日...
- 下载搜狐视频电视剧(搜狐电视剧下载安装)
-
搜狐视频APP下载好的视频想要导出到手机相册里方法如下1、打开手机搜狐视频软件,进入搜狐视频后我们点击右上角的“查找”,找到自已喜欢的视频。2、在“浏览器页面搜索”窗口中,输入要下载的视频的名称,然后...
- 永久免费听歌网站(丫丫音乐网)
-
可以到《我爱音乐网》《好听音乐网》《一听音乐网》《YYMP3音乐网》还可以到《九天音乐网》永久免费听歌软件有酷狗音乐和天猫精灵,以前要跳舞经常要下载舞曲,我从QQ上找不到舞曲下载就从酷狗音乐上找,大多...
- 音乐格式转换mp3软件(音乐格式转换器免费版)
-
有两种方法:方法一在手机上操作:1、进入手机中的文件管理。2、在其中选择“音乐”,将显示出手机中的全部音乐。3、点击“全选”,选中所有音乐文件。4、点击屏幕右下方的省略号图标,在弹出菜单中选择“...
- 电子书txt下载(免费的最全的小说阅读器)
-
1.Z-library里面收录了近千万本电子书籍,需求量大。2.苦瓜书盘没有广告,不需要账号注册,使用起来非常简单,直接搜索预览下载即可。3.鸠摩搜书整体风格简洁清晰,书籍资源丰富。4.亚马逊图书书籍...
- 最好免费观看高清电影(播放免费的最好看的电影)
-
在目前的网上选择中,IMDb(互联网电影数据库)被认为是最全的电影网站之一。这个网站提供了各种类型的电影和电视节目的海量信息,包括剧情介绍、演员表、评价、评论等。其还提供了有关电影制作背后的详细信息,...
- 孤单枪手2简体中文版(孤单枪手2简体中文版官方下载)
-
要将《孤胆枪手2》游戏的征兵秘籍切换为中文,您可以按照以下步骤进行操作:首先,打开游戏设置选项,通常可以在游戏主菜单或游戏内部找到。然后,寻找语言选项或界面选项,点击进入。在语言选项中,选择中文作为游...
欢迎 你 发表评论:
- 一周热门
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
