跳到主要内容

递归扁平文件

2024年07月02日
柏拉文
越努力,越幸运

一、认识


多层嵌套的目录结构扁平化并删除所有多级嵌套目录 实现的效果如下:

扁平前

dir/
|-- file1.txt
|-- sub_dir1/
| |-- file2.txt
| |-- sub_sub_dir1/
| |-- file3.txt
|-- sub_dir2/
|-- file4.txt
dir2/
|-- file1.txt
|-- sub_dir1/
| |-- file2.txt
| |-- sub_sub_dir1/
| |-- file3.txt
|-- sub_dir2/
|-- file4.txt
dir3/
|-- file1.txt
|-- sub_dir1/
| |-- file2.txt
| |-- sub_sub_dir1/
| |-- file3.txt
|-- sub_dir2/
|-- file4.txt

扁平后

dir/
|-- file1.txt
|-- file2.txt
|-- file3.txt
|-- file4.txt
dir2/
|-- file1.txt
|-- file2.txt
|-- file3.txt
|-- file4.txt
di3/
|-- file1.txt
|-- file2.txt
|-- file3.txt
|-- file4.txt

二、实现


#!/bin/bash

recursive_move_files() {
local base_dir="$1"
local root_dir="$2"
local index="$3"
local has_files=false

for entry in "$base_dir"/*; do
if [ -f "$entry" ]; then
filename=$(basename "$entry")
target_move="$root_dir/$filename"

while [ -e "$target_move" ]; do
filename="${filename%.*}_${index}.${filename##*.}"
target_move="$root_dir/$filename"
((index++))
done

mv "$entry" "$target_move"
echo "Moved file '$entry' to '$target_move'"
has_files=true
elif [ -d "$entry" ]; then
recursive_move_files "$entry" "$root_dir" 0
if [ "$(ls -A "$entry")" ]; then
has_files=true
fi
rmdir "$entry" 2>/dev/null
fi
done
}

directories=$(find . -mindepth 1 -maxdepth 1 -type d)

for dir in $directories; do
root_dir=$(realpath "$dir")
echo "Processing directory: $root_dir"
recursive_move_files "$dir" "$root_dir" 0
find "$dir" -type d -empty -delete
done

echo "Done."
  • directories=$(find . -mindepth 1 -maxdepth 1 -type d): 获取当前目录下的所有一级子目录

  • for dir in $directories; do: 遍历每个一级子目录并调用递归函数

  • root_dir=$(realpath "$dir"): 转化为绝对路径

  • recursive_move_files "$dir" "$root_dir" 0:

  • find "$dir" -type d -empty -delete: 在主循环处理完成后,使用 find "$dir" -type d -empty -delete 命令来递归查找并删除空目录。通过这种方式,脚本可以更可靠地确保在所有文件移动完成后再删除空目录,避免了因为并发操作或递归调用导致的删除失败问题。

  • rmdir "$entry" 2>/dev/null: 尝试删除空目录,忽略错误信息。在 mvrmdir 命令执行时,添加了错误处理(2>/dev/null)来忽略可能的错误消息,确保脚本的平稳执行。