如何让Shell脚本遍历目录及子目录检查文件是否存在
修改Shell脚本以递归搜索子目录中的文件
基础修改版本(适合小目录/短文件列表)
直接替换原脚本的文件检查逻辑,用find实现递归查找:
#!/usr/bin/env bash # 检查文件列表中的文件是否存在于指定目录及其子目录中 if [ $# -ne 2 ]; then echo "用法: $0 <文件名列表路径> <要检查的根目录>" exit 1 fi # 定义输出文件路径 FOUND_FILE="/cygdrive/c/temp/shellscript/filesfound.txt" NOT_FOUND_FILE="/cygdrive/c/temp/shellscript/filesNOTfound.txt" # 清空输出文件(避免累积旧数据) > "$FOUND_FILE" > "$NOT_FOUND_FILE" while IFS=$'\t\r' read -r file; do # 跳过空行 [[ -z "$file" ]] && continue # 在目标目录及其子目录中查找该文件,找到第一个匹配就停止以提升效率 if find "$2" -type f -name "$file" -print -quit | grep -q .; then echo "$file" >> "$FOUND_FILE" else echo "$file" >> "$NOT_FOUND_FILE" fi done < "$1"
高效优化版本(适合大目录/长文件列表)
先缓存目标目录下所有文件名到关联数组,再批量检查,大幅降低重复搜索的开销:
#!/usr/bin/env bash # 高效检查文件列表中的文件是否存在于指定目录及其子目录中 if [ $# -ne 2 ]; then echo "用法: $0 <文件名列表路径> <要检查的根目录>" exit 1 fi FOUND_FILE="/cygdrive/c/temp/shellscript/filesfound.txt" NOT_FOUND_FILE="/cygdrive/c/temp/shellscript/filesNOTfound.txt" > "$FOUND_FILE" > "$NOT_FOUND_FILE" # 用关联数组存储所有已存在的文件名 declare -A existing_files # 递归遍历目标目录的所有文件,缓存文件名(兼容含空格、换行等特殊字符的文件名) while IFS= read -r -d '' full_path; do filename="${full_path##*/}" existing_files["$filename"]=1 done < <(find "$2" -type f -print0) # 遍历文件列表进行检查 while IFS=$'\t\r' read -r file; do [[ -z "$file" ]] && continue if [[ -n "${existing_files["$file"]}" ]]; then echo "$file" >> "$FOUND_FILE" else echo "$file" >> "$NOT_FOUND_FILE" fi done < "$1"
执行命令
调用方式和原脚本一致:
./test.sh /cygdrive/c/temp/shellscript/file_list.txt \ /cygdrive/c/temp/shellscript/test
关键修改说明
- 替换原脚本的直接文件检查逻辑,改用
find实现全目录递归搜索 - 增加空行跳过、输出文件清空处理,避免无效检查和数据累积
- 高效版本通过一次性缓存所有文件名,将多次重复的
find调用转为数组快速查找,适合处理大规模目录和长文件列表场景
内容的提问来源于stack exchange,提问作者Matti45
相关产品推荐
相关产品推荐

