如何删除library目录下未在filenames.txt中列出的子目录?
问题解决:删除library下未在filenames.txt中列出的子目录
原脚本的问题在于循环变量$file是带完整路径的字符串(比如library/ABC),但filenames.txt里只存了纯目录名(比如ABC),所以grep永远匹配不到任何内容,导致所有library/*的条目都被执行rm -r删除。
以下是几种修复后的解决方案:
方案1:提取目录名后精准匹配
修改脚本,先用basename提取纯目录名,再用锚定正则确保整行匹配,同时只处理目录避免误删文件:
for dir in library/* do # 跳过非目录条目 [ -d "$dir" ] || continue # 提取纯目录名 dir_name=$(basename "$dir") # 精准匹配filenames.txt中的整行内容 grep "^$dir_name$" filenames.txt &> /dev/null || rm -r "$dir" done
方案2:用固定字符串匹配更安全
如果目录名包含正则特殊字符(比如.、*),用grep -F做固定字符串匹配更稳妥:
for dir in library/* do [ -d "$dir" ] || continue dir_name=$(basename "$dir") # -F: 固定字符串匹配;-x: 整行匹配;-q: 静默不输出结果 grep -Fxq "$dir_name" filenames.txt || rm -r "$dir" done
方案3:预加载允许列表(适合大量子目录场景)
如果library下子目录很多,先把允许的目录名加载到数组,循环判断效率更高:
# 读取filenames.txt内容到数组,跳过空行 mapfile -t allowed_dirs < <(grep -v '^$' filenames.txt) for dir in library/* do [ -d "$dir" ] || continue dir_name=$(basename "$dir") # 检查是否在允许列表内 found=0 for allowed in "${allowed_dirs[@]}"; do [ "$allowed" = "$dir_name" ] && found=1 && break done # 不在列表则删除 [ $found -eq 0 ] && rm -r "$dir" done
重要提醒
- 测试阶段先把
rm -r换成echo rm -r,确认要删除的目录正确后再执行实际删除操作 - 操作前务必备份
library目录下的重要数据,避免误删 - 如果
filenames.txt中有带空格的目录名,上述脚本因使用双引号包裹变量,能正确处理这种情况
内容的提问来源于stack exchange,提问作者Wang
相关产品推荐
相关产品推荐

