Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Traversing SubDir and Execute Unix Command

by neversaint (Deacon)
on Nov 08, 2008 at 16:05 UTC ( #722411=perlquestion: print w/replies, xml ) Need Help??

neversaint has asked for the wisdom of the Perl Monks concerning the following question:

Dear Masters,
I have the following subdirectories:
-dir1 |_ file1.gz |_ ... |_ file1000.gz ... -dir100 |_file1.gz |_ ... |_ file300.gz
What I am trying to do is to traverse "dir*" and execute "gunzip" command on the files inside them. I tried this code, but doesn't work:
for my $sd (@dirs) { system("cd $sd"); system("gunzip *.gz"); }
Please advice what's wrong with the above construct?

neversaint and everlastingly indebted.......

Replies are listed 'Best First'.
Re: Traversing SubDir and Execute Unix Command
by Corion (Pope) on Nov 08, 2008 at 16:08 UTC

    system("cd $sd") doesn't behave the way you think it does. It starts the cd command, which immediately exits again. The current directory of the parent process (your Perl script) is not changed.

    To change the directory, see chdir. Also see File::Find, if you haven't already.

Re: Traversing SubDir and Execute Unix Command
by ig (Vicar) on Nov 08, 2008 at 17:59 UTC

    find2perl makes this easy. It takes the same arguments as the find command and produces a script for you. It comes with perl on unix, linux and Windows.

    Running the command

    find2perl /some/directory -name '*.gz' -exec gunzip {} \;


    #! /usr/bin/perl -w eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if 0; #$running_under_some_shell use strict; use File::Find (); # Set the variable $File::Find::dont_use_nlink if you're using AFS, # since AFS cheats. # for the convenience of &wanted calls, including -eval statements: use vars qw/*name *dir *prune/; *name = *File::Find::name; *dir = *File::Find::dir; *prune = *File::Find::prune; sub wanted; sub doexec ($@); use Cwd (); my $cwd = Cwd::cwd(); # Traverse desired filesystems File::Find::find({wanted => \&wanted}, '/some/directory'); exit; sub wanted { /^.*\.gz\z/s && doexec(0, 'gunzip','{}'); } sub doexec ($@) { my $ok = shift; my @command = @_; # copy so we don't try to s/// aliases to consta +nts for my $word (@command) { $word =~ s#{}#$name#g } if ($ok) { my $old = select(STDOUT); $| = 1; print "@command"; select($old); return 0 unless <STDIN> =~ /^y/; } chdir $cwd; #sigh system @command; chdir $File::Find::dir; return !$?; }
Re: Traversing SubDir and Execute Unix Command
by Perlbotics (Bishop) on Nov 08, 2008 at 17:17 UTC

    Is this limited to *NIX? FWIW, you can merge your system calls into one:

    for my $sd (@dirs) { system(qq{cd "$sd" && gunzip *.gz}); }
    Personally, I would add a check for system's return value and redirect gunzips output. For more robustness it might be better (slightly slower) to first scan for all *.gz files below @dirs and then decompress each file individually. That would allow to check the success of the decompression operation for each individual file - if that matters.

Re: Traversing SubDir and Execute Unix Command
by Cody Pendant (Prior) on Nov 08, 2008 at 22:50 UTC
    Just a quick note, even if "cd" was what you wanted, it wouldn't have worked after the first time because when you're in "dir001" you can't do "cd dir002" unless dir001" is the parent of "dir002".

    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...
Re: Traversing SubDir and Execute Unix Command
by crusher (Acolyte) on Nov 08, 2008 at 19:16 UTC

    to change the current directory do as the following example:

    use Cwd; chdir("C:\\Perl") || die "Error changing the directory ($!)";
    my $cwd =getdcwd();

    Now cwd holds the full path to the working directory. Hope this helps...

Re: Traversing SubDir and Execute Unix Command
by mhearse (Chaplain) on Nov 08, 2008 at 21:42 UTC
    One idea would be to just use the shell...
    find top_dir/ -type f -name '*.gz' | xargs gunzip
Re: Traversing SubDir and Execute Unix Command
by Anonymous Monk on Nov 09, 2008 at 12:57 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://722411]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2020-09-24 21:49 GMT
Find Nodes?
    Voting Booth?
    If at first I donít succeed, I Ö

    Results (135 votes). Check out past polls.