- 文档
- 教程
- DevOps
- 运维
【免费下载链接】devops-exercises
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
本篇指南围绕开源仓库 devops-exercises 中
topics/shell系列练习 "Empty Files"(习题原文、官方参考答案)展开,讲解如何编写一个 Bash 脚本,删除指定目录及其嵌套子目录中的所有空文件。读完本文,你将掌握for循环遍历、-s文件大小测试、find递归搜索以及空文件清理的安全写法,并能把思路复用到磁盘清理、日志归档、构建产物回收等真实运维场景。
一、题目回顾:目标与约束
原练习(topics/shell/empty_files.md)给出的目标非常简洁:
Write a script to remove all the empty files in a given directory (including nested directories)
即:编写一个脚本,删除给定目录中的全部空文件,并且必须包含嵌套子目录。该练习被归类在topics/shell/README.md的 "Shell Scripting Exercises" 表格中,难度标记为Basic,主题为Misc,是整套 shell 练习(Hello World、Basic date、Factors、Argument Check、Files Size、Count Chars、Sum、Number of Arguments、Directories Comparison、Host Status)中的一环,适合在掌握变量、条件判断、for循环之后练习文件系统操作。
二、官方参考答案逐行拆解
仓库给出的解决方案(topics/shell/solutions/empty_files.md)如下:
#! /bin/bash for x in * do if [ -s $x ] then continue else rm -rf $x fi done逐行解读其原理:
#! /bin/bash:Shebang 行,声明用 Bash 解释器执行。仓库 README 的自测题也强调/bin/bash是 Bourne-again shell,功能完善、语法更佳,可执行绝大多数脚本。for x in *:让 shell 对当前目录下的每个条目(文件名或目录名)做通配符展开,逐个绑定到变量$x。注意:*默认不包含隐藏文件(以.开头),也不递归进入子目录。if [ -s $x ]:-s是 Bash 的文件测试运算符,判断文件存在且大小大于 0。条件为真(文件非空)时continue跳过;为假(空文件)则进入else分支。rm -rf $x:删除该条目。由于空文件大小为零,-s测试为假,因此会被删除。
需要特别指出的局限:
- 官方版本只能清理当前目录第一层的空文件/空目录,无法满足题目中 "including nested directories"(含嵌套目录)的要求;
- 它对空目录也会执行
rm -rf(-s对空目录同样为假),需要结合需求判断是否符合预期; - 未加双引号
"$x",当文件名包含空格或通配符字符时会出问题; - 未做任何参数校验,也没有提示输出。
三、对照同系列练习,理解脚本设计模式
"Empty Files" 在仓库中属于topics/shell系列的一部分,对比同目录其他题解(solutions 目录)可以总结出几条 Bash 脚本设计的惯用模式:
- Shebang 风格:
files_size.md、count_chars.md等使用#!/usr/bin/env bash(更便于在 PATH 中定位 bash),官方答案用的#! /bin/bash则直接指定绝对路径,两者均可接受。 - 循环遍历:本题和 Files Size 题解(
for i in $(ls -S1); do ... done)都演示了for循环遍历目录条目的写法,是 shell 习题的基础考点。 - 条件判断:与 Argument Check 题解 使用的
[[ ${1} == "pizza" ]]双括号条件、Directories Comparison 题解 使用的if test $# -ne 2类似,本题的[ -s $x ]属于单括号测试表达式,是test命令的简写形式。 - 退出码用法:Host Status 题解 中
ping失败后依据$?判断是否发告警邮件,说明脚本中"检查命令结果再决定分支"是常见模式;本题则通过-s测试的返回真伪决定删除与否。
四、升级方案一:用find递归删除嵌套目录中的空文件
原官方答案没有真正实现"嵌套目录"递归,最直接、最安全的改进是借助find:
#!/usr/bin/env bash # 用法: ./remove_empty.sh <目录> target_dir="${1:-.}" if [ ! -d "$target_dir" ]; then echo "Error: $target_dir is not a directory" >&2 exit 1 fi find "$target_dir" -type f -empty -delete echo "Empty files under $target_dir have been removed."要点说明:
-type f:只匹配普通文件,避免误删目录;-empty匹配大小为 0 的文件;-delete直接删除匹配项。- 三者组合即"递归删除给定目录树内所有空文件",完整满足原题 "including nested directories" 的目标。
- 用
-type d -empty可单独清理空目录(如find "$target_dir" -type d -empty -delete,注意应先深后浅以避免目录层级问题)。 - 如需"预览而不删除",把
-delete换成-print即可列出所有将被删除的空文件,这是生产环境最稳妥的演练方式。
五、升级方案二:保留for循环语义的递归版本
若希望保留官方答案的for循环教学思路,同时补齐递归能力,可结合find的输出驱动循环:
#!/usr/bin/env bash target_dir="${1:-.}" while IFS= read -r -d '' file; do if [ ! -s "$file" ]; then echo "Removing empty file: $file" rm -- "$file" fi done < <(find "$target_dir" -type f -print0)设计要点:
-print0与read -d ''配合,以 NUL 分隔文件名,可正确处理含空格、换行或特殊字符的文件名;[ ! -s "$file" ]即"文件不存在或大小为零"(-s取反),与官方答案的if [ -s $x ]逻辑互补但语义更严谨;rm -- "$file"中--防止以-开头的文件名被误认为选项,双引号防止分词与通配符展开;- 增加了
echo提示,让每次删除可审计、可回查。
六、边界情况与生产环境注意事项
无论采用哪种写法,处理空文件清理时都应考虑以下边界:
- 只删除空文件而非空目录:官方答案因
-s对空目录同样为假,会把空目录一并rm -rf;若需求仅限文件,务必加-type f或[ -f "$x" ]判断。 - 隐藏文件:
for x in *不匹配.开头的文件,find默认会遍历隐藏文件——两种行为差异需根据清理目标确认。 - 权限问题:无写权限的文件/目录会导致
rm或find -delete失败;可先用-print模拟,或对失败退出码做处理。 - 符号链接:
find -type f默认不跟随符号链接,需明确是否清理链接指向的空目标。 - 安全删除:
rm -rf是危险命令,本文仅作技术讲解;实际使用建议先-print预览,或把文件移入回收目录而非直接rm。
七、与本仓库其他模块的联系与延伸
topics/shell目录在仓库中对应 README 与 12 道基础练习题,从变量、算术、条件、循环到函数、case 语句循序渐进;"Empty Files" 的 Misc 定位恰好是综合运用for循环与文件测试运算符的典型代表。同时,仓库 scripts 目录中的 count_questions.sh 使用set -eu并借助grep | awk统计练习题数量、回写 README,展示了真实运维脚本对"失败即退出、可重复执行"的追求——与之对比,删除空文件的脚本同样建议加上set -e(按 README 自测题的说明,set -e可在命令失败时立即退出脚本,避免连锁错误)。如果你已掌握本练习,可继续挑战同系列难度为 Intermediate 的 Host Status(探测主机存活)与 Directories Comparison(目录差异比对),进一步巩固 shell 实战能力。
小结:官方答案用 10 行代码演示了 Bash 的for循环与-s测试,但受限于通配符展开不递归的特性,实际生产中推荐find -type f -empty -delete或"find -print0+ 循环"的方案,才能真正覆盖嵌套目录,并在文件名安全、空目录误删、可预览性等方面做到生产可用。
- 文档
- 教程
- DevOps
- 运维
【免费下载链接】devops-exercises
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
相关推荐
devops-exercises 实战:用 Bash 脚本清理目录中的空文件(Empty Files 练习精讲)
devops exercises 实战:用 Bash 脚本清理目录中的空文件(Empty Files 练习精讲) 导读 本文围绕 devops exercise
文档教程DevOps运维devops-exercises Shell 实战:用 for 循环打印当前目录下所有文件与目录的大小(Files Size 练习精解)
devops exercises Shell 实战:用 for 循环打印当前目录下所有文件与目录的大小(Files Size 练习精解) 本篇技术指南围绕 de
文档教程DevOps运维Backstage 软件目录中注销与删除组件(Entity)的完整实战指南
Backstage 软件目录中注销与删除组件(Entity)的完整实战指南 导读 在 Backstage 中,软件目录(Software Catalog)里的实
开发者门户后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考