简体   繁体   English

使用regexp基于原始文件夹仅比较和重命名目录中的文件

[英]compare and rename only files in a directory using regexp based on a original folder

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(原始)位于相同位置的文件将被重命名为原始文件。

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

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

I would recommend a combination of Path::Class and Path::Class::Rule . 我建议结合使用Path::ClassPath::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. 该脚本基本上会扫描__DATA__节中的文件和目录,以在特殊的测试目录中创建该文件和目录。 Then the subsequent section of code actually fixes the folder2 directory based off the information in folder1 . 然后,随后的代码部分实际上根据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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM