I need to rename only files in sub-directories of a folder based on another folder (original folder) and its sub-directories ...
我需要重命名基于另一个文件夹(原始文件夹)及其子目录的文件夹子目录中的文件...
Folder1 contain the correct files name so if a file in some sub-directory under folder2 and exist in same location as folder1 (original) will be renamed as original file.
Folder1包含正确的文件名,因此如果folder2下的某个子目录中存在与folder1(original)相同的位置的文件将被重命名为原始文件。
Example :
示例:
.
├── 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
after running "diff -qr /folder1 /folder2" I got the differences between these two folders is this case are :
运行“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
2 个解决方案
#1
1
I would recommend a combination of Path::Class
and Path::Class::Rule
.
我建议使用Path :: Class和Path :: Class :: Rule的组合。
The most difficult part of creating a solution to a problem like this is testing it. I therefore provide a completely self-contained script that creates a testing environment based off the example structure that you provided.
为这样的问题创建解决方案最困难的部分就是测试它。因此,我提供了一个完全独立的脚本,该脚本根据您提供的示例结构创建测试环境。
This script basically scans the __DATA__
section for files and directories to create in a special testing directory. Then the subsequent section of code actually fixes the folder2
directory based off the information in folder1
.
该脚本基本上扫描__DATA__部分以查找要在特殊测试目录中创建的文件和目录。然后,后续的代码部分实际上根据folder1中的信息修复了folder2目录。
Note, this will require installation of the two above cpan modules and their dependencies.
注意,这将需要安装上面两个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
Outputs:
输出:
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
#2
1
You can use the general strategy detailed in “Better way to rename files based on multiple patterns” which breaks down the renaming task in three stages:
您可以使用“更好地重命名基于多个模式的文件”中详述的一般策略,该策略分三个阶段分解重命名任务:
job_select | job_strategy | job_process
where job_select
is responsible for selecting the objects of your job, job_strategy
prepares a processing plan for these objects and job_process
eventually executes the plan.
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
#1
1
I would recommend a combination of Path::Class
and Path::Class::Rule
.
我建议使用Path :: Class和Path :: Class :: Rule的组合。
The most difficult part of creating a solution to a problem like this is testing it. I therefore provide a completely self-contained script that creates a testing environment based off the example structure that you provided.
为这样的问题创建解决方案最困难的部分就是测试它。因此,我提供了一个完全独立的脚本,该脚本根据您提供的示例结构创建测试环境。
This script basically scans the __DATA__
section for files and directories to create in a special testing directory. Then the subsequent section of code actually fixes the folder2
directory based off the information in folder1
.
该脚本基本上扫描__DATA__部分以查找要在特殊测试目录中创建的文件和目录。然后,后续的代码部分实际上根据folder1中的信息修复了folder2目录。
Note, this will require installation of the two above cpan modules and their dependencies.
注意,这将需要安装上面两个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
Outputs:
输出:
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
#2
1
You can use the general strategy detailed in “Better way to rename files based on multiple patterns” which breaks down the renaming task in three stages:
您可以使用“更好地重命名基于多个模式的文件”中详述的一般策略,该策略分三个阶段分解重命名任务:
job_select | job_strategy | job_process
where job_select
is responsible for selecting the objects of your job, job_strategy
prepares a processing plan for these objects and job_process
eventually executes the plan.
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