递归展平根目录中的子目录并维护一级子目录结构

递归展平根目录中的子目录并维护一级子目录结构

我有一个大的n级目录,结构如下:

root
  |
   subdir1
      |
       sub_subdir1
           |
            ....(n-2 levels).....
                                 |
                                  file1
  |
   subdir2
      |
       sub_subdir2
           |
            ....(n-2 levels).....
                                 |
                                  file2

我想展平目录,以便所有级别 1子目录包含文件。我还想将级别 2 删除为 (n-1)子子目录因为它们不包含文件。请注意,子目录都有不同的名称。

期望的结果

root
  |
   subdir1
      |
       file1
  |
   subdir2
      |
       file2

我发现很多帖子解释了方法压扁目录,但没有解释如何以受控方式执行此操作,即

  • 通过指定要展平的级别
  • 或者对根目录中的所有子目录递归执行此操作

答案1

使用 zsh:

cd /root
for subdir in subdir*
do
  mv "$subdir"/**/*(.) "$subdir"
  rm -r "$subdir"/*(/)
done

这:

  1. 更改“/root”目录(来自您的示例)
  2. 循环遍历每个名​​为的子目录subdir*(同样来自您的示例:匹配 subdir1 和 subdir1)
  3. 将该子目录下的(预期的,但会匹配所有)匹配文件移动到该子目录中。这使用了 zsh 的**递归 globbing 功能,然后受到 glob 限定符的限制,*(.)该限定符表示:此目录中的任何条目都是普通文件
  4. 移动文件后,递归删除该子目录下的每个子目录;这再次使用 zsh glob 限定符*(/),它表示匹配目录条目。

答案2

在 bash 中,执行以下操作:

shopt -s dotglob
for d in root/*/
do
        find "$d" -type f -exec mv -i -t "$d" {} +
        find "$d" -mindepth 1 -type d -delete
done

这会查看“ root”中的所有内容,包括点文件。如果您不需要查看点文件,请忽略shopt -s dotglob.警告:请勿添加.*或 命令。root/.*for

/正如Jeff所建议的, glob()末尾的只为我们提供了子目录,因此我们不需要测试每一个子目录(例如,使用 )。root/*/if

对于每一个子目录of root,找到该子目录及其下的所有文件并将它们移动到该子目录中。用于 -i防止覆盖文件(例如,如果您有多个名为file1 Distributed under 的文件subdir1)。  -i 意思是“交互式”,它会询问你是否应该覆盖现有文件。请注意,它可能拒绝这样做,即使你说“是”。如果您的版本 mv不支持该-t选项,请将命令替换mv

        find "$d" -type f -exec mv -i {} "$d" ';'

然后删除顶级子目录下的所有子目录。请注意,如果没有移动任何文件,此 ( find ...  ) 将失败。-delete

这部分受到启发德罗伯特的回答 到 展平嵌套目录

相关内容