测试环境:
- 创建从
0
到 的目录并用从到 的9
文件填充它们a
z
$ mkdir {0..9} && touch {0..9}/{a..z}
- 的结果
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
如何转换输出,使其看起来像这样:
./0a
./0b
...
./9y
./9z
答案1
使用 Perl 的独立rename
命令:
rename -n 's|/||' */*
如果一切正常,请删除-n
然后删除剩余的空目录。
rmdir {0..9}
答案2
借助 POSIX 工具,
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
调用 shell 并为每个文件执行 for 循环。
dirn="${f%/*}"
通过排除(并包括)文件名中最后一个斜杠之后的所有内容来获取父目录名称。${f##*/}
通过排除文件名中最后一个斜杠之前(并包括)的所有内容来获取不带路径的文件名。
这两个 shell 结构的作用与dirname
和basename
,所以该命令的等效形式是
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
,尽管这个应该慢一些,因为它需要为每个文件生成两个额外的进程。
如果您不需要进入多个目录(如您的示例所示),则可以使用一个简单的 shell 循环来完成:
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done