是否有一个命令行单行程序可以将文件夹的所有直接子文件夹的内容移动到文件夹本身并删除子文件夹(现在为空)?即消除文件夹层次结构中的某个级别?
为了绝对清晰,应该保留更深的子文件夹结构。
我已经遇到过几次这个问题了,我有点失望,这似乎不是 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/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
答案3
mv */* . && rmdir *
将子目录中的所有内容移动到当前目录。 rmdir 不会删除目录,除非它们是空的,所以第二部分只会删除空目录。