http://qs1969.pair.com?node_id=11150107

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

This is a simple script which sorts TV show episodes into the right folders, it comes down to this basic example:

### I run this from the command line: /usr/bin/perl mover.pl The.Rookie.S05E14.720p.HEVC.x265-MeGusta[eztv.r +e].mkv

The script dies here:

unless ( -e $ARGV[0] ) { die("$ARGV[0] doesn't exist"); }

But:

If I skip the file-exists test and go right to moving the file to the correct folder, I can do this:

say "move command: 'mv $ARGV[0] ./r/'"; system("mv $ARGV[0] ./r/");

The mv command in the system() call fails with "No such file or directory", but the exact same command, if I copy and paste it from the perl script's output and hit enter, works just fine.

Is it the brackets in the filename? I tried escaping them and it make no difference. The only wrinkle I can think of is that this is happening on MacOS, but the files in question are on a share from a Linux NAS, could that be causing issues?

Replies are listed 'Best First'.
Re: Why does system("mv $x $y") not work when it works at the command line? (updated)
by haukex (Archbishop) on Feb 03, 2023 at 04:58 UTC

    First, you shouldn't be using system for that operation, you should be using Perl's builtin rename, or move from the core module File::Copy.

    Second, if you ever do need to run an external command, see my node Calling External Commands More Safely.

    Update: Additionally, when you run your Perl script from the command line, you need to properly escape/quote the filename (e.g. in single quotes) to prevent special characters in the filename (like the brackets) from being interpreted by the shell. Modern shells' tab completion can do this for you.

Re: Why does system("mv $x $y") not work when it works at the command line?
by sectokia (Pilgrim) on Feb 03, 2023 at 04:51 UTC
Re: Why does system("mv $x $y") not work when it works at the command line?
by hv (Prior) on Feb 03, 2023 at 03:04 UTC

    The shell will normally treat [xyz] as a character class, and attempt to match filenames on that basis. But if it finds no file matches for the expansion, it will instead pass the original characters as the argument:

    % ls t0 t1 % echo t[012] t0 t1 % echo t[xy] t[xy] %

    It isn't entirely clear to me what your filename is, or what your code is doing, but I suspect the shell behaviour is causing the confusion.

      This varies by shell. By default zsh will gripe if it can't find a match (although I think there's options enabled with setopt which will make it behave more like POSIX/ksh). For example the first works (because of course there's a file named foo . . . who doesn't have one?) but the second errors first and doesn't actually run the echo command.

      oscar:~ 1064> echo fo[ob] foo oscar:~ 1065> echo fo[xy] zsh: no matches found: fo[xy]

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

Re: Why does system("mv $x $y") not work when it works at the command line?
by misterperl (Pilgrim) on Feb 03, 2023 at 17:32 UTC

    system commands are generally the last resort.

    Also a lot easier to read and less prone to warnings:
    die "$ARGV[0] doesn't exist" unless @ARGV && -e $ARGV[0];
Re: Why does system("mv $x $y") not work when it works at the command line?
by harangzsolt33 (Chaplain) on Feb 03, 2023 at 02:49 UTC
    I would try this with a test file first. Create a file called test.txt and try to move it with your perl script. Works? Great. Then rename your mkv file to test.mkv and then move it. My guess is that the file name contains some special characters which is why it isn't working. But I could be wrong..
Re: Why does system("mv $x $y") not work when it works at the command line?
by Anonymous Monk on Feb 03, 2023 at 11:44 UTC
    Depends on what shell is being used... What filepaths ... Use absolute file paths (resolve if ya have ta)