【问题标题】:Shell script to run Perl script over every directory in a directory用于在目录中的每个目录上运行 Perl 脚本的 Shell 脚本
【发布时间】:2015-02-03 19:52:48
【问题描述】:

设置:

包含一年中每一天的目录的数据目录。即数据/2014-01-01/ 到 2014-12-31。我有一个 perl 脚本,我在每个日期目录中单独运行。

我正在尝试运行一个 shell 脚本来从数据中运行,并从 2014-02-15 到 2014-07-20 遍历每个目录,并在每个目录中运行 perl 脚本。 perl 脚本运行大约需要 20 秒。这是我到目前为止所拥有的,它只会在 2 月份运行,并且不会等待 perl 脚本完成。我希望它在该范围内的每个目录上运行,并等待循环内的 perl 脚本完成,然后再重新循环。

 #!/bin/bash

 folders=`find 2014-02*`

 for folder in $folders; do 
 cd $folder
 perl C:/Tools/script.pl
 cd ..
 done

【问题讨论】:

  • 为什么不将遍历的文件夹添加到perl脚本而不是单独的shell脚本?每个文件夹的 perl 脚本是否有本质上的不同?
  • 1 不要像这样迭代find 结果,请参阅this answer2 如果您之前cded 比一个目录更深,cd .. 不会带您返回。
  • find data/ -type d -name '2014-0[2-7]-(1[5-9]|20)' -exec C:/Tools/script.pl {} \; 我相信上面的命令会起作用(没有测试),但是构建一个可以采用任意起点和终点并应用您想要的任何逻辑的脚本似乎更合理。因为您可能不得不再次这样做。
  • @Biffen 感谢您提供的信息,但您有什么解决方案吗?
  • @Hunter 我会试试这个。这会等待 perl 脚本在每次迭代中完成吗?是的,我希望在脚本中实现它以便稍后再次运行。

标签: perl shell loops directory


【解决方案1】:

为什么不全部用 perl 来做呢?通过File::Find内置模块,它具有非常好的遍历能力。

将您的“脚本”封装为子程序。

#!/usr/bin/perl

use strict;
use warnings;
use File::Find;

sub your_script_sub {
    my ( $dir ) = @_;
    #do something with $dir. At a worst case, you could just run your script.
    #but there's no real reason to do that, as it's perl already. 
}

sub run_script_in_dirs {
   if ( -d $File::Find::name ) { 
        your_script_sub($File::Find::name);
    }
}

find ( \&run_script_in_dirs, "/path/to/your/dir" );

对于奖励积分 - 您可以使用线程来并行化您的“在目录中运行脚本”:

#!/usr/bin/perl
use strict;
use warnings;
use threads;
use Thread::Queue;

my $num_threads = 4;
my $dir_q = Thread::Queue -> new(); 

sub your_script_sub {
   while ( my $dir = $dir_q -> dequeue() ) {
          # do something in $dir;
   }
}

sub find_dirs_to_run_script {
   if ( -d $File::Find::name ) { 
        $dir_q -> enqueue($File::Find::Name);
    }
}

for ( 1..$num_threads ) {
   threads -> create ( \&your_script_sub );
}

find ( \&find_dirs_to_run_script, "/path/to/dirs" );

$dir_q -> end();

foreach my $thr ( threads -> list() ) { $thr -> join() }

【讨论】:

  • 看起来不错。看起来目录的范围不包含在其中,对吗?另外我的其他 perl 脚本使用另一个程序进行分析,因此一次只能使用一次。
  • 没有。 perl 的方式是使用该子例程,您可以测试$_$File::Find::name 以匹配您正在寻找的模式。您确定您的其他程序一次只能使用一个吗?这是一些许可问题吗?
  • 是的,它使用另一个程序进行分析并计算大量数据。不能一次运行到数据集。
  • 耸耸肩。那么,第一个例子。但就像我说的那样 - 您拥有一个一次只能运行一个实例的程序并不是特别常见。 (除了资源限制)。这将遍历/path/to/dirs 下的任何目录。
  • if ( -d $File::Find::name ) { your_script_sub($File::Find::name);我将名称更改为 2015-02-15 到 2015-07-20 范围?
猜你喜欢
  • 2012-05-02
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 2019-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多