扁平化文件夹结构

nun*_*nos 10 bash shell-script rename

我有这个文件夹结构:

??? foo1
?   ??? bar1.txt
?   ??? bar2.txt
??? foo2
?   ??? bar3.txt
?   ??? bar4 with a space.txt
??? foo3
    ??? qux1
        ??? bar5.txt
        ??? bar6.txt
Run Code Online (Sandbox Code Playgroud)

我想将其展平,每个文件夹级别之间都有一个下划线:

??? foo1_bar1.txt
??? foo1_bar2.txt
??? foo2_bar3.txt
??? foo2_bar4 with a space.txt
??? foo3_qux1.bar6.txt
??? foo3_qux1_bar5.txt
Run Code Online (Sandbox Code Playgroud)

我环顾四周,但没有找到任何可行的解决方案,主要是我认为是因为我的问题有两个特殊性:根目录中可能有多个文件夹级别,还因为某些文件可能有空格。

知道如何在 bash 中完成此操作吗?谢谢!

编辑:运行 gleen jackman 建议的答案我得到了这个:

在此处输入图片说明

第一级文件夹有两个下划线。知道如何避免这种情况或只是重命名它以便只是一个下划线吗?谢谢。

gle*_*man 17

find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;
Run Code Online (Sandbox Code Playgroud)

echo如果您满意,请删除它。不要担心回显命令不显示引号,脚本将正确处理带有空格的文件。

如果要删除现在为空的子目录:

find */ -depth -type d -exec echo rmdir '{}' \; 
Run Code Online (Sandbox Code Playgroud)


Gil*_*not 5

使用 perl 的重命名:

find . -depth -type f -exec rename 's@(?<!\.)/@_@g' -- {} \;
Run Code Online (Sandbox Code Playgroud)

输出

$ find -type f
./foo2_bar4 whit a space.txt
./foo3_qux1_bar6.txt
./foo2_bar3.txt
./foo3_qux1_bar5.txt
./foo1_bar2.txt
./foo1_bar1.txt
Run Code Online (Sandbox Code Playgroud)

笔记

  • 我用消极的眼光看后面 (?<!\.)不要碰第一个./
  • 我保留空目录,请随意:

    find . -depth -type d -exec rm {} \;

警告 还有其他同名的工具可能会也可能不会这样做,所以要小心。

如果您运行以下命令 ( GNU)

$ file "$(readlink -f "$(type -p rename)")"
Run Code Online (Sandbox Code Playgroud)

你有这样的结果

.../rename: Perl script, ASCII text executable
Run Code Online (Sandbox Code Playgroud)

并且不包含:

ELF
Run Code Online (Sandbox Code Playgroud)

那么这似乎是正确的工具 =)

如果没有,将其设为默认值(通常已经是这种情况)Debian和衍生工具,例如Ubuntu

$ sudo update-alternatives --set rename /path/to/rename
Run Code Online (Sandbox Code Playgroud)

(替换/path/to/rename为您的perl's rename命令路径。


如果您没有此命令,请搜索您的包管理器进行安装或手动安装


最后但并非最不重要的一点是,这个工具最初是由 Perl 的父亲 Larry Wall 编写的。