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

I currently use a PHP (it's what I know) script to dig through specified directories for certain file types (mkv and avi) and feeds those files found to HandBrakeCLI to compress and convert them to an m4v file. I'm trying to change this from a PHP script to a perl script and I'm having a couple problems.

First problem is my directories and files have spaces in them. So the input file to HandBrake is fine, but the output stops at the first space.

Second problem, I need to change these files from .avi or .mkv to .m4v. If there was a way to strip off the extension and use just the base name for my output file, then I could append .m4v on to the end, that would be great (this is what I do with the PHP script).

Below is what I've written on my own so far, if there is a better way to do any of this, feel free to poke fun at me but please correct me, I'm trying to learn perl and get away from my nasty habit of relying on PHP and bash for my scripting needs.

#!/usr/bin/env perl use File::Find::Rule; use Data::Dumper; my $handbrake = '/usr/local/bin/HandBrakeCLI'; my $preset = 'AppleTV'; my $itunes = '/Volumes/Media/iTunes/iTunes Media/Automatically Add to +iTunes/'; my $tvtag = '/usr/local/bin/tvtag-sickbeard.pl'; my @files = find( file => name => [qw/ *.mkv *.avi / ], in => @ARGV ); $list = join("\n",@files," "); print "\nFound the following files to convert:\n\n$list\n"; foreach $file (@files) { print $file . "\n"; system "$handbrake -i '$file' -o $file\.m4v --preset=$preset"; }

Replies are listed 'Best First'.
Re: Variables with spaces and changing file extensions
by ikegami (Patriarch) on Oct 17, 2011 at 03:33 UTC

    Better yet, avoid the shell completely.

    my $error; for my $in_qfn (@in_qfns) { ( my $out_qfn = $in_qfn ) =~ s/\.(?:mkv|avi)\z/m4v/; system($handbrake => ( '-i' => $in_qfn, '-o' => $out-qfn, "--preset=$preset, )); if ($?) { warn("Error converting $in_qfn\n"); ++$error; } } exit(1) if $error;
Re: Variables with spaces and changing file extensions
by Khen1950fx (Canon) on Oct 17, 2011 at 03:34 UTC
    Make sure to start your script with strictures:
    use strict; use warnings; use File::Find::Rule;
    For file names with spaces, wrap them with quotes. For example:
    my $itunes = '"/Volumes/Media/iTunes/iTunes Media/Automatically Add to + iTunes/"';
    As for your $list, I would eliminate that and call File::Find::Rule in list context like:
    my(@files) = File::Find::Rule
    Here's how I would do it:
    #!/usr/bin/perl use strict; use warnings; use File::Find::Rule; my $handbrake = '/usr/local/bin/HandBrakeCLI'; my $preset = 'AppleTV'; my $itunes = '"/Volumes/Media/iTunes/iTunes Media/Automatically Add to + iTunes/"'; my $tvtag = '/usr/local/bin/tvtag-sickbeard.pl'; my(@files) = File::Find::Rule ->file() ->name( qr/\.(mkv|avi)$/ ) ->in( @ARGV ); @files = join("\n", @files, ''); print "\nFound the following files to convert:\n\n@files\n"; foreach my $file(@files) { print $file . "\n"; system "$handbrake -i '{$file}' -o '$file.m4v' --preset=$preset"; }
Re: Variables with spaces and changing file extensions
by keszler (Priest) on Oct 17, 2011 at 03:26 UTC

    In your system command you're single-quoting $file, but not quoting the output file. Adding single-quotes around the output file should solve the spaces-in-filename problem. Alternately, you could "escape" the spaces by putting a backslash in front of each one.

    The file extension can be changed with the "substitution" operator s///. (Think search and replace.)

    foreach my $infile (@files) { print $infile . "\n"; # escape spaces # $infile =~ s[ ][\\ ]g; my $outfile = $infile; $outfile =~ s/\.(?:mkv|avi)\z/m4v/; system "$handbrake -i '$infile' -o '$outfile' --preset=$preset"; # + without escaped spaces #system "$handbrake -i $infile' -o $outfile --preset=$preset"; # w +ith escaped spaces }

Re: Variables with spaces and changing file extensions
by calebcall (Sexton) on Oct 17, 2011 at 03:48 UTC
    Awesome! Thanks guys, this has got this part of the script working how I expect it to. Now that I have this, I think I'll be able to finish the rest of the small tasks (moving original avi/mkv file to an archive directory and passing the new file to a tagging script, then copying it to my iTunes directory. Thanks again.