Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^2: how to move multiple files

by ObiPanda (Acolyte)
on Sep 08, 2023 at 19:41 UTC ( [id://11154328] : note . print w/replies, xml ) Need Help??


in reply to Re: how to move multiple files
in thread how to move multiple files

Thank you to both posters.
I was able to get a test case of code working based on my script, with the help of this code. (I'm not a professional coder.) I think it's solved.

If you don't mind Ken, can you very briefly tell me what is the purpose of the array in the first line of mv_tmp_to_phone?

my ($src, $dest) = @_;
btw. The single quotes were because the files and file paths at times include spaces.

Replies are listed 'Best First'.
Re^3: how to move multiple files
by kcott (Archbishop) on Sep 08, 2023 at 22:24 UTC

    If you don't mind Ken, can you very briefly tell me what is the purpose of the array in the first line of mv_tmp_to_phone?

    my ($src, $dest) = @_;

    The short (and simplistic) answer is that is how to capture the parameters sent to a subroutine.

    However, I imagine you're asking that because $src and $dest already exist in the code and could be used directly in mv_tmp_to_phone().

    Whilst that is true, it is a poor coding habit to get into because those variables in the subroutine would be reliant upon variables declared and used outside of the subroutine. This has the problems that you may have encountered with using global variables in other scripts.

    The $src and $dest used in mv_tmp_to_phone() are lexically scoped to mv_tmp_to_phone() and are not reliant on what those variables are called elsewhere in the code. To demonstrate, here's another version (move_to_phone_2.pl) where I move those files back again but, outside of mv_tmp_to_phone(), they have different names (i.e. $s and $d).

    #!/usr/bin/env perl use strict; use warnings; use File::Copy 'move'; my ($s, $d) = reverse qw{Temp Phone}; mv_tmp_to_phone($s, $d); sub mv_tmp_to_phone { my ($src, $dest) = @_; system ls => '-lR'; my @files = glob("$src/*"); print "$_\n" for @files; move($_, $dest) for @files; system ls => '-lR'; }

    Here's a run of that code:

    ken@titan ~/tmp/pm_11154302_move_files $ ./move_to_phone_2.pl .: total 2 -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl drwxr-xr-x 1 ken None 0 Sep 8 18:05 Phone drwxr-xr-x 1 ken None 0 Sep 8 18:05 Temp ./Phone: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 ./Temp: total 0 Phone/file1 Phone/file2 .: total 2 -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl drwxr-xr-x 1 ken None 0 Sep 9 07:07 Phone drwxr-xr-x 1 ken None 0 Sep 9 07:07 Temp ./Phone: total 0 ./Temp: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2

    For completeness on a discussion of passing variables to subroutines, a more modern and improved method is to use Signatures. These were introduced as an experimental feature in v5.20.0 (see "perl5200delta: Experimental Subroutine signatures") and became a stable feature in v5.36.0 (see "perl5360delta: Core Enhancements: use v5.36").

    As a side note, I do not recommend the use of experimental features in production code as they can often change before becoming stable features. From that last link (with my emphasis added): "Introduced in Perl version 5.20.0, and modified several times since, the subroutine signatures feature is now no longer considered experimental."

    The original version of the code I posted should work under any Perl5 version. Here's another version, move_to_phone_3.pl, for version v5.36.0 and later.

    #!/usr/bin/env perl use v5.36; use File::Copy 'move'; my ($source, $destination) = qw{Temp Phone}; mv_tmp_to_phone($source, $destination); sub mv_tmp_to_phone ($src, $dest) { system ls => '-lR'; my @files = glob("$src/*"); say for @files; move($_, $dest) for @files; system ls => '-lR'; }

    And here's a run of that code:

    ken@titan ~/tmp/pm_11154302_move_files $ ./move_to_phone_3.pl .: total 3 -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl -rwxr-xr-x 1 ken None 319 Sep 9 08:14 move_to_phone_3.pl drwxr-xr-x 1 ken None 0 Sep 9 07:07 Phone drwxr-xr-x 1 ken None 0 Sep 9 07:07 Temp ./Phone: total 0 ./Temp: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 Temp/file1 Temp/file2 .: total 3 -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl -rwxr-xr-x 1 ken None 319 Sep 9 08:14 move_to_phone_3.pl drwxr-xr-x 1 ken None 0 Sep 9 08:15 Phone drwxr-xr-x 1 ken None 0 Sep 9 08:15 Temp ./Phone: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 ./Temp: total 0

    — Ken

      Wow! Thank you! I had to study some CompSci many years, including Perl, so I'm familiar with passing variables and the good practice of using local variables; but, with the constraints of a young kid around, I don't have the time to delve as deeply or fully into topics as I would like. So I honestly appreciate the time you took for explaining this. Have a great weekend.
      However, I imagine you're asking that because...

      I'm curious why you used a sub given that it's a script, not a module, and it only gets called once.

        I'm curious why you used a sub given that it's a script, not a module, and it only gets called once

        Bod, further to kcott's excellent reply (especially "a subroutine abstracts functionality and promotes reuseability; it has nothing to do with script vs. module" ++) a few more thoughts on the tricky topic of how best to test end user scripts.

        My preferred approach is to abstract the work the script does into CPAN-like modules and unit test each module using Test::More and the prove command. Accordingly, I strive to keep my script mainlines as short as is practicable. There are many examples of this approach on the CPAN; the perltidy command, for example, is effectively a one-liner:

        exit Perl::Tidy::perltidy( argv => $arg_string );

        Though I'm not a fan, an alternative approach, concocted by brian_d_foy (who has made 93 fewer posts than you ;-), is modulinos (how a script becomes a module).

        G'day Bod,

        "I'm curious why you used a sub given that it's a script, not a module, and it only gets called once."

        My example code only called it once for demonstration purposes. A subroutine abstracts functionality and promotes reuseability; it has nothing to do with script vs. module. The OP's production code may want to use it multiple times.

        Here's move_to_phone_4.pl which, after adding some files for my explanation to you, shows:

        • Multiple calls to mv_tmp_to_phone().
        • Variable and hard-coded parameters.
        • Handling of filenames containing spaces.
        • The fact that glob("$src/*") works and does not require glob("'$src/*'").
        • An absence of files in the source directory is not a problem.

        [Those last three points are mainly for the OP's benefit.]

        #!/usr/bin/env perl use v5.36; use File::Copy 'move'; my ($source, $destination) = qw{Temp Phone}; mv_tmp_to_phone($source, $destination); mv_tmp_to_phone(qw{For_Bod Phone}); sub mv_tmp_to_phone ($src, $dest) { system ls => '-lR'; my @files = glob("$src/*"); say for @files; move($_, $dest) for @files; system ls => '-lR'; }

        The output's getting lengthy but here's a sample run:

        ken@titan ~/tmp/pm_11154302_move_files $ ./move_to_phone_4.pl .: total 4 drwxr-xr-x 1 ken None 0 Sep 9 08:42 For_Bod -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl -rwxr-xr-x 1 ken None 319 Sep 9 08:14 move_to_phone_3.pl -rwxr-xr-x 1 ken None 356 Sep 9 09:02 move_to_phone_4.pl drwxr-xr-x 1 ken None 0 Sep 9 08:15 Phone drwxr-xr-x 1 ken None 0 Sep 9 08:15 Temp ./For_Bod: total 0 -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 3' -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 4' ./Phone: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 ./Temp: total 0 .: total 4 drwxr-xr-x 1 ken None 0 Sep 9 08:42 For_Bod -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl -rwxr-xr-x 1 ken None 319 Sep 9 08:14 move_to_phone_3.pl -rwxr-xr-x 1 ken None 356 Sep 9 09:02 move_to_phone_4.pl drwxr-xr-x 1 ken None 0 Sep 9 08:15 Phone drwxr-xr-x 1 ken None 0 Sep 9 08:15 Temp ./For_Bod: total 0 -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 3' -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 4' ./Phone: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 ./Temp: total 0 .: total 4 drwxr-xr-x 1 ken None 0 Sep 9 08:42 For_Bod -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl -rwxr-xr-x 1 ken None 319 Sep 9 08:14 move_to_phone_3.pl -rwxr-xr-x 1 ken None 356 Sep 9 09:02 move_to_phone_4.pl drwxr-xr-x 1 ken None 0 Sep 9 08:15 Phone drwxr-xr-x 1 ken None 0 Sep 9 08:15 Temp ./For_Bod: total 0 -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 3' -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 4' ./Phone: total 0 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 ./Temp: total 0 For_Bod/file 3 For_Bod/file 4 .: total 4 drwxr-xr-x 1 ken None 0 Sep 9 09:02 For_Bod -rwxr-xr-x 1 ken None 337 Sep 8 18:05 move_to_phone.pl -rwxr-xr-x 1 ken None 335 Sep 9 07:07 move_to_phone_2.pl -rwxr-xr-x 1 ken None 319 Sep 9 08:14 move_to_phone_3.pl -rwxr-xr-x 1 ken None 356 Sep 9 09:02 move_to_phone_4.pl drwxr-xr-x 1 ken None 0 Sep 9 09:02 Phone drwxr-xr-x 1 ken None 0 Sep 9 08:15 Temp ./For_Bod: total 0 ./Phone: total 0 -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 3' -rw-r--r-- 1 ken None 0 Sep 9 08:42 'file 4' -rw-r--r-- 1 ken None 0 Sep 8 17:50 file1 -rw-r--r-- 1 ken None 0 Sep 8 17:50 file2 ./Temp: total 0

        — Ken

Re^3: how to move multiple files
by AnomalousMonk (Archbishop) on Sep 08, 2023 at 22:23 UTC
    ... what is the purpose of the array in the first line of mv_tmp_to_phone?

    my ($src, $dest) = @_;

    Taking the liberty of answering for kcott...
    https://perldoc.perl.org/perlvar#@_ is the argument list passed to a subroutine. Assignment to lexicals allows "speaking" variable names to be used rather than $_[0] $_[1] as would otherwise be necessary. This assignment also defeats aliasing of the original argument variables used in the call to the subroutine, which avoids many subtle and sometimes perplexing side effects.


    Give a man a fish:  <%-{-{-{-<

Re^3: how to move multiple files
by kcott (Archbishop) on Sep 08, 2023 at 23:38 UTC
    "btw. The single quotes were because the files and file paths at times include spaces."

    Take a look at my later response to Bod. It contains a number of additional points which may be relevant to you.

    — Ken