提问者:小点点

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


我需要根据另一个文件夹(原始文件夹)及其子目录仅重命名文件夹子目录中的文件…

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

共2个答案

匿名用户

我推荐组合路径::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