如何在目录中递归查找特定文件,通过为子目录名添加前缀重命名,并将其移动到不同的目录

时间:2013-09-26 01:45:37

标签: macos perl

我是perl noob,并尝试做以下事情:

  1. 以递归方式在目录中搜索具有特定字符串的文件。 Say string是'abc.txt'
  2. 该文件可以位于两个不同的子目录中,例如dir_1或dir_2
  3. 找到文件后,如果在dir_1中找到该文件,请将其重命名为dir_1_abc.txt。如果它在dir_2中,则将其重命名为dir_2_abc.txt。
  4. 找到并重命名所有文件后,将它们全部移至名为dir_3的新目录
  5. 我不在乎是否必须使用任何模块才能完成此任务。我一直在尝试使用File :: Find :: Rule和File :: copy,但没有得到所需的结果。这是我的示例代码:

    #!/usr/bin/perl -sl
    use strict;
    use warnings;
    use File::Find::Rule;
    use File::Copy;
    
    my $dir1 = '/Users/macuser/ParentDirectory/logs/dir_1'  
    my $dir2 = '/Users/macuser/ParentDirectory/logs/dir_2'  
    
    #ideally I just want to define one directory but because of the logic I am using in IF 
    #statement, I am specifying two different directory paths
    
    my $dest_dir = '/Users/macuser/dir_3';
    my(@old_files) = find( 
                  file => (),
                  name => '*abc.txt', 
                  in => $dir1, $dir2 ); #not sure if I can give two directories, works with on
    
    
    foreach my $old_file(@old_files) {
    
            print $old_file;    #added this for debug
    
        if ($dest_dir =~ m/dir_1/)       
        {
          print "yes in the loop";
          rename ($old_file, "dir_1_$old_file");
              print $old_file;
              copy "$old_file", "$dest_dir";
        } 
    
           if ($dest_dir =~ m/dir_2/)       
       {
          print "yes in the loop";
          rename ($old_file, "dir_2_$old_file");
              print $old_file;
              copy "$old_file", "dest_dir";
       } 
       }
    

    上面的代码不会更改文件名,而是当我在内部打印$ old_file时,它会吐出整个目录路径,找到文件,并且路径前面分别是dir_1和dir_2。有些事情是可怕的错误。请帮忙。

2 个答案:

答案 0 :(得分:0)

如果在重命名文件时可以将文件放在目标中,请尝试以下操作:

#!/usr/bin/perl
use strict;

use File::Find;
use File::Copy;

my $dest_dir = '/Users/macuser/dir_3';
foreach my $dir ('/Users/macuser/ParentDirectory/logs/dir_1', '/Users/macuser/ParentDirectory/logs/dir_2') {
    my $prefix = $dir; $prefix =~ s/.*\///;

    find(sub {
        move($File::Find::name, "$dest_dir/${prefix}_$_") if /abc\.txt$/;
    }, $dir);
}

如果您需要先进行所有重命名然后再将它们全部移动,您可以记住要移动的文件列表,也可以进行两次传递,确保第二次传递后的模式在初始化后仍然正常在第一遍中重命名。

答案 1 :(得分:0)

如果你有bash(我假设它在OSX中可用),你可以用几行(通常我把它们放在一行)。

destdir="your_dest_dir"
for i in `find /Users/macuser/ParentDirectory/logs -type f -iname '*abc.txt'  ` 
do  
    prefix=`dirname $i`
    if [[ $prefix = *dir_1* ]] ; then
        prefix="dir_1"
    fi

    dest="$destdir/${prefix}_`basename $i`"
    mv "$i" "$dest" 
done

此方法的优点是您可以在logs下拥有多个子目录,而无需指定它们。您也可以搜索blah_abc.txttada_abc.txt等文件。如果您想要完全匹配juse abc.txt,而不是*abc.txt