为了防止删除空的子目录,我个人认为最简单的方法是先移动到一个临时目录,然后将临时目录重命名为旧目录。假设要处理的目录是
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/b
将变成b
。
--backup=t
与cp
或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
rmdir folder/*/
rmdir
会报错非空目录,所以不会造成任何损害。 - muru