我需要根据另一个文件夹(原始文件夹)及其子目录仅重命名文件夹子目录中的文件…
Folder1包含正确的文件名,因此如果folder2下的某个子目录中的文件与folder1(原始)位于同一位置,则将重命名为原始文件。
示例:
.
├── folder1
│ ├── Somedir
│ │ ├── file.xml
│ │ ├── doc
│ │ │ ├── CHANGELOG
│ │ │ ├── TEST
│ │ │ ├── file_test.txt
│ │ │ ├── sample
│ │ │ ├── README
│ │ │ ├── mydir
│ │ │ │ ├── exploitation-file.rst
│ │ │ │ ├── advanced-file.txt
.
├── folder2
│ ├── Somedir
│ │ ├── file.xml
│ │ ├── doc
│ │ │ ├── CHANGELOG
│ │ │ ├── TEST
│ │ │ ├── filetest.txt
│ │ │ ├── sample
│ │ │ ├── README
│ │ │ ├── mydir
│ │ │ │ ├── exploitationfile.rst
│ │ │ │ ├── advancedfile.txt
运行“diff-qr /folder1 /folder2”后,我得到了这两个文件夹之间的差异是这种情况:
/folder2/somedir/filetest.txt (missing underscore) vs /folder1/somedir/file_test.txt
/folder2/somedir/doc/mydir/exploitation-file.rst (missing hyphen) vs /folder1/somedir/doc/mydir/exploitation-file.rst
/folder2/somedir/doc/mydir/advanced-file.txt (missing hyphen) vs /folder1/somedir/doc/mydir/advanced-file.txt
我推荐组合路径::Class
和路径::Class::规则
。
为这样的问题创建解决方案最困难的部分是测试它。因此,我提供了一个完全独立的脚本,该脚本根据您提供的示例结构创建一个测试环境。
这个脚本基本上是在__DATA__
部分扫描文件和目录,以便在一个特殊的测试目录中创建。然后后面的代码部分实际上根据folder1
中的信息修复了folder2
目录。
请注意,这将需要安装上述两个cpan模块及其依赖项。
use strict;
use warnings;
use autodie;
use Path::Class;
use Path::Class::Rule;
my $testdir = dir('testing');
# Setup Testing Environment
$testdir->rmtree();
$testdir->mkpath();
chdir($testdir);
while (<DATA>) {
my ( $type, $name ) = split;
if ( $type eq 'd' ) {
dir($name)->mkpath();
} else {
file($name)->spew($name);
}
}
# Actual Solution
my $backup_dir = dir('folder1');
my $main_dir = dir('folder2');
my $next = Path::Class::Rule->new->file->name(qr{[_-]})->iter($backup_dir);
while ( my $file = $next->() ) {
my $correct_name = $file->basename();
( my $stripped_name = $correct_name ) =~ s{[_-]}{}g;
my $from_file = file( $main_dir, $file->dir->relative($backup_dir), $stripped_name );
my $to_file = file( $main_dir, $file->dir->relative($backup_dir), $correct_name );
if ( -e $from_file ) {
print "$from_file -> $to_file\n";
$from_file->move_to($to_file);
}
}
__DATA__
d folder1
d folder1/Somedir
f folder1/Somedir/file.xml
d folder1/Somedir/doc
f folder1/Somedir/doc/CHANGELOG
f folder1/Somedir/doc/TEST
f folder1/Somedir/doc/file_test.txt
f folder1/Somedir/doc/sample
f folder1/Somedir/doc/README
d folder1/Somedir/doc/mydir
f folder1/Somedir/doc/mydir/exploitation-file.rst
f folder1/Somedir/doc/mydir/advanced-file.txt
d folder2
d folder2/Somedir
f folder2/Somedir/file.xml
d folder2/Somedir/doc
f folder2/Somedir/doc/CHANGELOG
f folder2/Somedir/doc/TEST
f folder2/Somedir/doc/filetest.txt
f folder2/Somedir/doc/sample
f folder2/Somedir/doc/README
d folder2/Somedir/doc/mydir
f folder2/Somedir/doc/mydir/exploitationfile.rst
f folder2/Somedir/doc/mydir/advancedfile.txt
输出:
folder2/Somedir/doc/filetest.txt -> folder2/Somedir/doc/file_test.txt
folder2/Somedir/doc/mydir/advancedfile.txt -> folder2/Somedir/doc/mydir/advanced-file.txt
folder2/Somedir/doc/mydir/exploitationfile.rst -> folder2/Somedir/doc/mydir/exploitation-file.rst
您可以使用“基于多种模式重命名文件的更好方法”中详述的一般策略,该策略将重命名任务分为三个阶段:
job_select | job_strategy | job_process
其中job_select
负责选择作业的对象,job_strategy为这些对象准备一个处理计划,job_process最终执行该计划。
# job_select SRCDIR
# Find all files having a dash or a hyphen in name
job_select()
{
(cd "$1" && find . -type f -name '*[-_]*')
}
# job_strategy
# Compute the renaming plan
#
# This assume that wrong names are deduced from good names by removing `_` and `-`.
# The output has three columns,
#
# reldir|goodname|badname
#
# For instance, ./somedir/file_test.txt yields the plan
#
# ./somedir|file_test.txt|filestest.txt
job_strategy()
{
sed -e '
s@/\([^/]*\)$/@|\1@
h
s@^.*|@@
s@[-_]@@g
x
G
s/\n/|/
'
}
# job_process TGTDIR
{
cd "$1" || exit
IFS='|'
while read reldir goodname badname; do
relgoodname="$reldir/$goodname"
relbadname="$reldir/$badname"
if [ -r "$relbadname" ]; then
printf 'Rename %s to %s\n' "$relbadname" "$relgoodname"
mv "$relbadname" "$relgoodname"
else
printf 'Skip %s\n' "$relbadname"
fi
done
}
job_select /folder1 | job_strategy | job_process /folder2