扁平化文件夹结构

扁平化文件夹结构

我有这个文件夹结构:

├── foo1
│   ├── bar1.txt
│   └── bar2.txt
├── foo2
│   ├── bar3.txt
│   └── bar4 with a space.txt
└── foo3
    └── qux1
        ├── bar5.txt
        └── bar6.txt

我想将其扁平化,在每个文件夹级别之间使用下划线:

├── foo1_bar1.txt
├── foo1_bar2.txt
├── foo2_bar3.txt
├── foo2_bar4 with a space.txt
├── foo3_qux1.bar6.txt
└── foo3_qux1_bar5.txt

我环顾四周,没有找到任何有效的解决方案,主要是因为我的问题有两个特殊性:根文件夹内可能有多个文件夹级别,而且有些文件可能有空格。

知道如何在 bash 中实现这一点吗?谢谢!

编辑:运行格伦·杰克曼提出的答案我得到这个:

在此输入图像描述

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

答案1

find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;

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

如果您想删除现在空的子目录:

find */ -depth -type d -exec echo rmdir '{}' \; 

答案2

使用perl的重命名:

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

输出

$ 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

笔记

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

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

警告还有其他同名的工具可能能够也可能无法做到这一点,所以要小心。

如果运行以下命令 ( GNU)

$ file "$(readlink -f "$(type -p rename)")"

你有一个像这样的结果

.../rename: Perl script, ASCII text executable

并且不包含:

ELF

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

如果不是,则将其设为默认值(通常已经是这种情况)Debian并衍生如下Ubuntu

$ sudo update-alternatives --set rename /path/to/rename

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


如果您没有此命令,请搜索包管理器来安装它或手动做


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

答案3

pax...

pax -Xrwls '|/|_|g' */ "$PWD"

这将在当前目录中创建一个指向其子目录中所有文件的硬链接,_并将/.然后您可以检查结果并使用以下命令删除所有子目录...

rm -rf */

...一旦您确认结果符合您的喜好。

答案4

您可以尝试使用以下命令。

$ find -type f -exec bash -c 'mv $0 $(echo $0|sed "s/\//_/2")' {} \;

上述命令将移动文件,并且目录将保留,稍后可以删除。

$ ls
foo1_bar1.txt  foo1_bar2.txt  foo2_bar3.txt  foo2_bar4.txt  foo3_bar5.txt  foo3_bar6.txt

相关内容