使用 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.md
和 global_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
使用perl,具有完整的正则表达式功能来处理父目录的新情况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()
行。
我的目标是在子文件夹中找到所有名为 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.md
和 global_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
使用perl,具有完整的正则表达式功能来处理父目录的新情况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()
行。