Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

using an array in a while loop

by perlnewbie (Novice)
on Jan 31, 2022 at 09:31 UTC ( [id://11140989]=perlquestion: print w/replies, xml ) Need Help??

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

Hey, I've got a question about using a reference to an array in a while loop. My folders with the data from different subjects are named abc_001, abc_002, abc_003 and so on. Now I want to tell my script to go in each subfolder and do some processing steps for alle the subjects.

$i=1; while ($i<=4); {chdir ($i) or die "Konnte Verzeichnis $i nicht öffnen"; foreach ("T1_Map","T2_Map", "PD_Map", "T2STAR_Map") { system ("fslreorient2std $_.nii.gz $_._swapped.nii.gz") system ("bet $_._swapped.nii.gz $_._swappedbrain.nii.gz -m"); } chdir (".."); } continue { $i ++; }

When I name the folder with "1", "2" etc. there is no problem, but I would prefer naming them abc_001, abc_002 etc. Is there a option I define my subjects using an array and referencing them in the while loop, so the while loop uses the subjects from the array? Thanks a lot!

Replies are listed 'Best First'.
Re: using an array in a while loop
by choroba (Cardinal) on Jan 31, 2022 at 09:47 UTC
    Normally, you shouldn't need the number at all:
    my @dirs = ('/path/to/dir1', '/some/other/path/to/dir2', '/dir3'); for my $dir (@dirs) { ... }

    To populate the array with the names, you can use a map:

    my @dirs = map { sprintf 'abc_%03d', $_ } 1 .. 100;

    If you really need the array index, loop over the indices rather than the elements themselves:

    for my $i (0 .. $#dirs) { my $dir = $dirs[$i]; ... }

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: using an array in a while loop
by davies (Prior) on Jan 31, 2022 at 11:41 UTC

    In addition to choroba's (++) reply above, you might look at File::Find, a core module that does a lot of work for you. File::Find::Rule enables code that I find clearer, but it's not core.

    Regards,

    John Davies

Re: using an array in a while loop
by bliako (Monsignor) on Jan 31, 2022 at 12:29 UTC

    Even with helpful indentation your sscript has errors. while : why the semicolon at the end? continue { } what do you want to do with that? answer to me: well to increment $i obviously.

    $i=1; while ($i<=4); { chdir ($i) or die "Konnte Verzeichnis $i nicht öffnen"; foreach ("T1_Map","T2_Map", "PD_Map", "T2STAR_Map") { system ("fslreorient2std $_.nii.gz $_._swapped.nii.gz") system ("bet $_._swapped.nii.gz $_._swappedbrain.nii.gz -m"); } chdir (".."); } continue { $i ++; }

    In order to construct a filename from a basename and an index, as others said, just concatenate the basename with the index: my $filename = 'abc_' . sprintf("%.3d", $i); (note the 3-zero padding convention). Or File::Find the files you want (based on a regex pattern) as some other monk said.

    For chdir back to your current dir, this is more convenient for me:

    use Cwd qw(cwd); my $oridir = cwd; chdir("a/b/c/"); ... # back to original dir chdir($oridir);

    Of course there's also File::pushd which only halfway meets the convenience and simplicity of *nix's pushd/popd

Re: using an array in a while loop
by BillKSmith (Monsignor) on Jan 31, 2022 at 16:26 UTC
    If the number of 'subject' folder names is small, your idea of putting them in an array has merit. Use foreach rather than while.
    se strict; use warnings; my @subjects = qw(abc_001 abc_002 abc_003); foreach my $subject (@subjects) { chdir($subject) or die "Konnte Verzeichnis $subject nicht öffnen"; foreach ( "T1_Map", "T2_Map", "PD_Map", "T2STAR_Map" ) { system("fslreorient2std $_.nii.gz $_._swapped.nii.gz"); system("bet $_._swapped.nii.gz $_._swappedbrain.nii.gz -m"); } chdir(".."); }
    Bill
Re: using an array in a while loop
by Anonymous Monk on Jan 31, 2022 at 16:38 UTC

    Because this is Perl, There Is More Than One Way To Do It. Here is an array-less solution given your statement about how the folders are named:

    for ( my $i = 1; $i <= 4; $i++ ) {
        my $dir_name = sprintf 'abc_%03d', $i;
        chdir $dir_name or die "Unable to change to $dir_name: $!";
        ...
        chdir '..';
    }
    

    But in real life I would probably use File::Find like everyone else.

      A perlish equivalent:

      for my $i ('001' .. '004') { my $dir_name = "abc_$i"; chdir $dir_name or die "Unable to change to $dir_name: $!"; ... chdir '..'; }

      🦛

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11140989]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2024-04-19 12:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found