使用文件夹重命名文件';带bash`find的名称`
我的目标是在子文件夹中找到名为使用文件夹重命名文件';带bash`find的名称`,bash,cp,perl,Bash,Cp,Perl,我的目标是在子文件夹中找到名为README.md的所有文件,并将其复制到output文件夹中,使用原始文件夹的名称作为新名称 好吧,听起来很复杂。让我们看一个具体的例子: baselines ├── combined_tree_local_conflict_obs │ ├── README.md │ └── sparse_small_apex_maxdepth2_spmaxdepth30.yaml └── global_density_obs ├── README.md
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\u tree\u local\u conflict\u obs.md
和global\u density\u 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 {} \;
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 \;
比如在评论中解释
$(basename$(dirname{}))
在开始查找之前运行。它不可能对找到的特定文件的名称进行操作
我有一些更好的解决方案
第一:
cd baselines
然后,像这样重复使用代码:
find . -type f -name "README.md" -exec bash -c '
echo cp "$1" "./output/$(dirname "$1").md"
' -- {} \;
或
检查
或
当输出看起来适合您时,请删除echo
命令(不要尝试为bashSTDIN
)
使用,以及完整的正则表达式功能来处理父目录基线的新情况:
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/${1}.md@;
print "$file => $mod\n";
#copy("$file", "$mod") or die $!;
}
}
}, @ARGV);
' ./baselines/
这是在调试模式下,要真正执行此操作,请删除
print
命令并取消对copy()
行的注释。请添加所需内容structure@GillesQuenot添加了$(basename$(dirname{}))
在find
偶数启动之前运行。它不可能对找到的特定文件的名称进行操作。顺便说一句,您在这里所做的一切都包含在中。请在下次有2个答案时不要更改规则sed:1:“s@@@@@g/g”:替换命令中的错误标志:“/”我想他的意思是's@@@g'
。这不起作用:$(dirname{}sed's@@@g'))
命令替换在find
启动之前调用。顺便说一句,运行生成的命令的安全方法可能是在取消echo
的情况下重新调用脚本,而不是将输出传输到sh
或bash
。否则,如果某个人的目录名中包含$(rm-rf~)
,那么他可能会度过非常糟糕的一天!(虽然也可以让它生成安全的命令;例如,通过将内部的echo
更改为类似printf“cp%q%q\n”“$file”“。/output/$(dirname“$file”).md“
)这样可以使用新名称中文件的完整路径,但我只想保留文件所在目录的名称!我得到cp基线/combined\u tree\u local\u conflict\u obs/README.md./output/baselines/combined\u tree\u local\u conflict\u obs.md
而我想要cp基线/combined\u tree\u local\u conflict\u obs/README.md./output/combined\u tree\u local\u conflict\u obs.md
@MasterScrat输入结构和查找不匹配命令。好的,那就行了。我希望有一个更通用的解决方案,它不需要目录中的cd
,但这就可以了!
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/${1}.md@;
print "$file => $mod\n";
#copy("$file", "$mod") or die $!;
}
}
}, @ARGV);
' ./baselines/