如何解散所有子文件夹

如何解散所有子文件夹

是否有一个命令行单行程序可以将文件夹的所有直接子文件夹的内容移动到文件夹本身并删除子文件夹(现在为空)?即消除文件夹层次结构中的某个级别?

为了绝对清晰,应该保留更深的子文件夹结构。

我已经遇到过几次这个问题了,我有点失望,这似乎不是 Dolphin 的功能,也不是其他人正在努力解决的问题。

我怀疑这可能需要分成两步,移动子文件夹的内容,并删除子文件夹。但是,这可能会产生删除空的二级子文件夹的不良副作用。

答案1

实际上不是真正的一行:

find . -mindepth 2 -maxdepth 2 -print -exec mv --backup=numbered -t . '{}' + \
&& find . -mindepth 1 -maxdepth 1 -type d -empty -delete

首先找到深度恰好为 2 的子文件夹中的所有内容并将其移动到.。然后查找并删除当前目录中的所有空文件夹。

  • 如果您有同名的文件/文件夹,它们将被重命名original_filename.~n~(n 表示 1、2、3......)。
  • 请注意,这将删除所有空的子文件夹。

更新:

我对上面的解决方案不满意。太多注意事项和问题。例如,当 --backup=numbered 重命名您要移动的文件夹的父文件夹时...

mkdir -p test/test
mv test/test . --backup=numbered
mv: cannot move 'test/test' to './test': No such file or directory

最好使用临时目录来避免问题。临时目录应该位于同一文件系统上,以避免复制文件。

tmpdir=$(mktemp -d)
find . -mindepth 2 -maxdepth 2 -print -exec mv -b -t $tmpdir '{}' +
find . -mindepth 1 -maxdepth 1 -type d -empty -delete
mv -b $tmpdir/* .
rm $tmpdir

答案2

为了防止删除空子目录,我认为最简单的方法是移动到临时目录,然后将临时目录重命名为旧目录。假设要删除的目录是foo,而您想foo/*/*将其改为foo/*。请执行以下操作:

tar c --remove-files foo | tar xv --strip-components=2 --backup=t --one-top-level=temp
mv temp foo
  • 使用--remove-files,第一个tar将在处理文件时删除它们,最后删除foo自身。
  • 使用--strip-components=2,第二个将从它正在提取的路径中tar砍掉,因此将变成。foo/*/foo/a/bb
  • --backup=tcp与或mv- 制作编号备份副本相同。但是,mv如果目录名称相同,则会制作目录副本,但tar会合并目录并备份文件。
  • --one-top-level=temp告诉tar创建一个名为的目录temp并在其中提取文件。

例如:

$ tree bar
bar
├── a
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
├── b
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
└── c
    ├── c
    │   └── bar
    ├── d
    │   └── bar
    ├── e
    │   └── bar
    └── f
        └── bar

运行命令后tar

$ tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=temp
bar/a/e/
bar/a/e/bar
bar/a/f/
bar/a/f/bar
bar/a/c/
bar/a/c/bar
bar/a/d/
bar/a/d/bar
bar/b/e/
bar/b/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~1~’
bar/b/f/
bar/b/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~1~’
bar/b/c/
bar/b/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~1~’
bar/b/d/
bar/b/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~1~’
bar/c/e/
bar/c/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~2~’
bar/c/f/
bar/c/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~2~’
bar/c/c/
bar/c/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~2~’
bar/c/d/
bar/c/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~2~’

$ tree temp
temp
├── c
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── d
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── e
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
└── f
    ├── bar
    ├── bar.~1~
    └── bar.~2~

4 directories, 12 files

通过tar输出,您可以看到何时tar重命名文件进行备份,从而可以跟踪哪些文件成为了哪些备份。


我有点惊讶它居然能起作用,但你实际上可以提供相同的目录名称,--one-top-level这样就无需重命名了。只需这个管道就足够了:

tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=bar

答案3

mv */* . && rmdir *

将子目录中的所有内容移动到当前目录。 rmdir 不会删除目录,除非它们是空的,所以第二部分只会删除空目录。

相关内容