使用 bash `find` 使用文件夹名称重命名文件

Renaming files using their folder's name with bash `find`

我的目标是在子文件夹中找到所有名为 README.md 的文件,并将它们复制到 output 文件夹中,使用原始文件夹的名称作为新名称。

好吧,这听起来很复杂。让我们看一个具体的例子:

baselines
├── combined_tree_local_conflict_obs
│   ├── README.md
│   └── sparse_small_apex_maxdepth2_spmaxdepth30.yaml
└── global_density_obs
    ├── README.md
    └── sparse_small_apex_expdecay_maxt1000.yaml

我想将 README.md 文件复制到 output 文件夹,名称为 combined_tree_local_conflict_obs.mdglobal_density_obs.md

所以最后我会:

baselines
├── output
│   ├── combined_tree_local_conflict_obs.md
│   └── global_density_obs.md
├── combined_tree_local_conflict_obs
│   ├── README.md
│   └── sparse_small_apex_maxdepth2_spmaxdepth30.yaml
└── global_density_obs
    ├── README.md
    └── sparse_small_apex_expdecay_maxt1000.yaml

我不明白为什么我的 bash 命令不起作用:

$ find baselines -type f -name "README.md" -exec echo output/$(basename $(dirname {})).md \;
output/..md
output/..md

(我还没有复制文件,只是打印它们的新路径来调试命令。)

查找命令确实有效:

$ find baselines -type f -name "README.md" -exec echo {} \;
baselines/combined_tree_local_conflict_obs/README.md
baselines/global_density_obs/README.md

提取文件夹名称确实有效:

$ echo $(basename $(dirname "baselines/combined_tree_local_conflict_obs/README.md"))
combined_tree_local_conflict_obs

但是!不知何故,当我把它们放在一起时,它不起作用。

我对如何以另一种方式解决这个问题不太感兴趣,而是想了解为什么我的命令不起作用。

这个呢

$ find baselines -type f -name "README.md" -exec echo output/$(dirname {}|sed 's@/@_@/g').md \;

喜欢Charles Duffy评论说明,

$(basename $(dirname {})) 在查找甚至开始之前运行。它不可能对找到的特定文件的名称进行操作。

我有一些更好的解决方案...

第一个:

cd baselines

然后,像这样重新使用您的代码:

find . -type f -name "README.md" -exec bash -c '
    echo cp "" "./output/$(dirname "").md"
' -- {} \;

find . -type f -name "README.md" -exec bash -c '
    for file; do
        echo cp "$file" "./output/$(dirname "$file").md"
    done
' -- {} +

勾选https://mywiki.wooledge.org/UsingFind

for file in */README.md; do
    echo cp "$file" "./output/$(dirname "$file").md"
done

当输出看起来不错时,请删除 echo 命令(不要试图喂 bash STDIN)。


cp ./combined_tree_local_conflict_obs/README.md ./output/./combined_tree_local_conflict_obs.md
cp ./global_density_obs/README.md ./output/./global_density_obs.md

使用,具有完整的正则表达式功能来处理父目录的新情况baselines

perl -MFile::Find -MFile::Copy -we '
    find({
        no_chdir => 1,
        wanted => sub {
             if (-f && m/README\.md$/) {
                 my $mod = my $file = $File::Find::name;
                 $mod =~ s@.*([^/]+)/.*@output/.md@;
                 print "$file => $mod\n";
                 #copy("$file", "$mod") or die $!;
             }
         }
     }, @ARGV);
' ./baselines/

这是调试模式,要真正做到这一点,请删除 print 命令并取消注释 copy() 行。