我有一个如下所示的目录树(简化后,实际上有数百个文件夹):
.
├── a
│ └── b
│ └── a.h5
├── b
│ ├── b
│ │ └── e.h5
│ └── c
│ ├── a.h5
│ └── b.h5
├── c
│ └── b
│ └── a.h5
├── d
│ ├── a.h5
│ └── e.h5
└── e
└── e.h5
基本上,有些.h5
文件的深度为 1(例如d/a.h5
, e/e.h5
),有些文件的深度为 2(例如b/b/e.h5,
b/c/b.h5
, ...)
我只想向上移动深度为 2 的文件,以便它们都位于深度 1,如下所示:
.
├── a
│ └── a.h5
├── b
│ ├── e.h5
│ ├── a.h5
│ └── b.h5
├── c
│ └── a.h5
├── d
│ ├── a.h5
│ └── e.h5
└── e
└── e.h5
我知道这与*/*/*.h5
我感兴趣的文件相匹配(通过测试ls */*/*.h5
),但我尝试过mv */*/*.h5 */*.h5
,结果弄得一团糟。
重复的文件最好通过重命名来处理,但提示也可以。我应该如何进行?
PS:我见过:
- https://superuser.com/questions/62141/how-to-move-all-files-from-current-directory-to-upper-directory
- 如何安全地将文件批量移动到一个目录?
但它们都适用于单个目录。
答案1
这应该是一个开始:
find . -mindepth 3 -maxdepth 3 -type f -execdir mv -i -v {} .. \;
要求mv -i
覆盖现有文件。-execdir
在执行命令之前更改文件的目录。
答案2
从你的目录结构来看:
$ tree
.
├── a
│ └── b
│ └── a.h5
├── b
│ ├── b
│ │ └── e.h5
│ └── c
│ ├── a.h5
│ └── b.h5
├── c
│ └── b
│ └── a.h5
├── d
│ ├── a.h5
│ └── e.h5
└── e
└── e.h5
12 directories, 8 files
使用这个for
循环:
$ for f in */*/*.h5; do mv -v -- "$f" "${f%/*}/../"; done
»a/b/a.h5“ -> »a/b/../a.h5“
»b/b/e.h5“ -> »b/b/../e.h5“
»b/c/a.h5“ -> »b/c/../a.h5“
»b/c/b.h5“ -> »b/c/../b.h5“
»c/b/a.h5“ -> »c/b/../a.h5“
这结果:
$ tree
.
├── a
│ ├── a.h5
│ └── b
├── b
│ ├── a.h5
│ ├── b
│ ├── b.h5
│ ├── c
│ └── e.h5
├── c
│ ├── a.h5
│ └── b
├── d
│ ├── a.h5
│ └── e.h5
└── e
└── e.h5
12 directories, 8 files
解释:
for f in */*/*.h5; do mv -v -- "$f" "${f%/*}/../"; done
for f in */*/*.h5
循环遍历所有需要的文件mv -v --
详细地感动他们。--
防止带破折号的文件名被解释为参数。"$f"
原始文件名${f%/*}/../
添加的包含该文件的目录的名称../
。该路径被解释为“向上一个目录”。
答案3
尝试
for x in */*/*.h5
do
mv "$x" "$(dirname $(dirname $x))"
done
如果目录名称中没有奇怪的字符。
或者,另一种选择:
ls */*/*.h5 | awk -F/ '{print "mv \"%s\" \"%s/%s\" \n",$0,$1,$3 ;}' | bash
您可以删除| bash
以获取预览。