Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用文件夹重命名文件';带bash`find的名称`_Bash_Cp_Perl - Fatal编程技术网

使用文件夹重命名文件';带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
命令(不要尝试为bash
STDIN


使用,以及完整的正则表达式功能来处理父目录基线的新情况:

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/