perl script chokes on dirs with spaces


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting perl script chokes on dirs with spaces
# 1  
Old 03-16-2009
PHP perl script chokes on dirs with spaces

Basically, I have a perl script that calls enables one to resume where a video file left off (i.e. where the user stopped playback) that chokes on files that are located in a path that contains spaces.

To make the situation a little more complicated, the perl script gets help from a bash script that analyzes the video file in question and passes file-specific switches to mplayer.

Both scripts need to be in the same dir and you must run them from that dir!

Here is the usage:
Code:
$ ./mplayer-resumer-vdpau.pl /path/to/file.avi

(You can use any video format that mplayer can play, like mpg, mkv, etc.)

The problem occurs when the path to the video file contains a space. The perl script doesn't handle it and passes the incorrect options to the file.

Example: I go to play ‘Test.mkv' located in /media/D/New\ CD/

Code:
$ ./mplayer-resumer-vdpau.pl /media/D/New\ CD/Test.mkv 
File not found: '/media/D/New'
Failed to open /media/D/New.
File not found: '/media/D/New'
Failed to open /media/D/New.

Can someone have a look at the code and help me fix this? I just don't know that much about perl to be useful.

Code to mplayer-resumer-vdpau.pl
Code:
#!/usr/bin/perl

use Shell;
use strict;
use POSIX qw(floor);

# Written by Bob Igo from the MythTV Store at http://MythiC.TV
# Email: bob@stormlogic.com
#
# If you run into problems with this script, please send me email

# CHANGE LOG:
# 3/9/2009
# Modded Bob's wonderful resumer script to work with the vdpau
# options detector script by nickca of the linhes forums.
#
#  http://www.knoppmythwiki.org/index.php?page=HardwareAcceleratedVideo
#
# You need to have both this and the vdpau-detector script in the same
# dir for this to work properly.  Also, change your default mplayer
# options in mythfrontend to read simply: # mplayer-resumer-vdpau.pl %s
#
# To tweak the shell commands for mplayer, edit the vdpau-detector script.
# It has a small README inside it as comments
# ENJOY!

# 5/3/2006
# Added last time started checking.
# If this script is restarted within $tdiff (default 5 seconds)
# then it will delete the file used to keep track of the videos
# resume position.

# PURPOSE:
# --------------------------
# This is a wrapper script to prove the concept of having MythTV
# resume playback of previously-stopped video where you left off.
# It's likely that a good solution will look different than this
# initial code.

# RATIONALE:
# --------------------------
# Watching 90% of a video and stopping causes you to return to the
# beginning again the next time you watch it.  Remembering where
# you were in the video and resuming at that position is a much nicer
# behavior for the user.
#
# By default, mplayer spits out timecode information that tells you
# where you are in the video, to the tenth of a second.  Mplayer also
# supports a seek feature on the command-line.  We can make use of these
# features to write an mplayer wrapper that will remember the last
# position in a video file and resume to it on playback.

# PARAMETERS:
# --------------------------
# see print_usage() below

# FILES:
# --------------------------
# $infile, the video to play
# $resumefile, the video's resume file (see get_resume_filename() below)

# KNOWN ISSUES:
# --------------------------
# Mplayer misreports the timecodes on .nuv MPEG-2 files.  Currently, anything
# captured via an HDTV tuner card and put into your /myth/video directory
# will fail with this resumer.
#
# Current theories include the timecode having to do with the show's broadcast
# time, recording time, or perhaps its upload time to the station that
# broadcast it.

# DESIGN LIMITATION:
# -------------------------
# If the video file to be played is on a read-only filesystem, or otherwise
# lives in a location that cannot be written to, resume will fail.  This is
# because the current implementation uses a file parallel to the video file
# to store the timecode.
#

my $infile;
my $resumefile;
my $mplayer_parameters;
my $fudge_factor=2; # number of additional seconds to skip back before playback
my $tnow;    # Time now.
my $tprev;   # Time the prog was last started. 
             # Returned from the modification time of the xx.resume file.
my $tdiff=5; # How many seconds before we should start from 
             # the beginning of the movie
#DEBUG
#open(DEBUG,">/tmp/debug") || die "unable to open debug file";

sub init () {
    $tnow = time();
    $infile = @ARGV[$#ARGV];

    $resumefile = &get_resume_filename($infile);
    # This returns the 9th element of the 13 element array 
    # created by the stat function.
    $tprev = (stat ($resumefile))[9]; 
    # if this file is restarted in less than 5 seconds then 
    # remove the .resume file
    if ( ($tnow - $tprev) < $tdiff ) {
        unlink($resumefile);
    }

    $mplayer_parameters = join(' ',@ARGV[0..$#ARGV-1]);
}

&init();
&save_time_offset(&mplayer($mplayer_parameters,$infile), $resumefile);

#close(DEBUG);

# For $pathname, return $path.$filename.resume
sub get_resume_filename () {
    my($pathname)=@_;
    
    my $idx = rindex($pathname,"/");

    if ($idx == -1) { # There was no "/" in $pathname
    return ".".$pathname.".resume";
    } else {
    # Now we need to split out the path from the filename.
    my $path = substr($pathname,0,$idx+1);
    my $filename = substr($pathname,$idx+1);
    return "$path.$filename.resume";
    }
}

# Calls mplayer and returns the last known video position
sub mplayer () {
    my($parameters,$infile)=@_;
    my $seconds=0;
    my $timecode=&get_time_offset($infile);
    my $mplayeropts=`./vdpau-detector $infile`; chomp $mplayeropts;
    my @lines = split "\n", $mplayeropts;
    my $last_line = pop(@lines);
    my $command = "mplayer $last_line $parameters -ss $timecode \"$infile\" 2>&1 2>/dev/null |";

    open(SHELL, $command);
    # The kind of line we care about looks like this example:
    # A:1215.2 V:1215.2 A-V:  0.006 ct:  0.210 207/201 13%  0%  1.9% 0 0 68%
    # But all we care to look at is the first number.
    
    while (<SHELL>) {
    #print DEBUG $_;
    if (m/A: *[0-9]+\.[0-9]/) { # See if this line has timecodes on it
        my $last_timecode_line = &extract_last_timecode_line($_);
        if ($last_timecode_line =~ m/ *([0-9]+\.[0-9]) V/) {
        $seconds=$1;
        }
    }
    }
    close(SHELL);

    return $seconds;

    sub extract_last_timecode_line () {
    my ($line)=@_;
    my @lines=split('A:',$line);
    return @lines[$#lines-1];
    }
}

# Save the last known video position
sub save_time_offset () {
    my($seconds, $resumefile)=@_;

    open(RESUMEFILE, ">$resumefile") || die "Unable to open $resumefile for writing";
    print RESUMEFILE "$seconds";
    close(RESUMEFILE);
}

# returns the number of seconds corresponding to the last known video position,
# in hh:mm:ss format, compatible with the "-ss" parameter to mplayer
sub get_time_offset () {
    my($videofile)=@_;
    my($resumefile) = &get_resume_filename($videofile);
    my $seconds=0;
    my $timecode;

    open(RESUMEFILE, "<$resumefile") || return "00:00:00";
    while(<RESUMEFILE>) {
    $seconds=$_;
    }
    close(RESUMEFILE);

    my $hours = floor($seconds/3600);
    $seconds = $seconds - $hours*3600;

    my $minutes = floor($seconds/60);
    $seconds = int($seconds - $minutes*60) - $fudge_factor;

    $timecode = sprintf "%02d:%02d:%02d",$hours,$minutes,$seconds;
#    print "TIMECODE: $timecode\n";
    return $timecode;
}

sub print_usage () {
    print "USAGE:\n";
    print "\t",$ARGV[0], "[mplayer parameters] video_file\n";
    print "\t","e.g. ",$ARGV[0], "-fs -zoom my.mpg\n";
    print "\t","Version 3/9/2009\n";
}

Code to vdpau-detector
Code:
#!/bin/bash

# This script written by nickca on the linhes forums
# Original page http://www.knoppmythwiki.org/index.php?page=HardwareAcceleratedVideo
#
# It's modded to allow vdpau switches commands to pass to a modded version of Bob Igo's
# mplayer-resumer.pl wrapper for mplayer
#
# User can customize commandline for mplayer by editing the appropriate sections below
# They include BASIC_OPTS, NOHD_OPTS, and LOW_OPTS

IAM=$0
FILE=$1

#if no input display usage
if [[ -z "$FILE" ]]; then
        echo usage: $0 /path/to/file
        exit
fi

MPLAYER="/usr/bin/mplayer"

# For a complete list of options, see the mplayer DOCS
# http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html
#

# Options for all videos: fullscreen, zoom, and use software eq
BASIC_OPTS="-fs -zoom"

# Options for non-HD videos: force aspect to 16x10 (to ensure video fills TV screen)
# You'll need to modify the ratio if your res differs
# Example: 1920x1080 = 1.778 = 16:9
# Example: 1680x1050 = 1.600 = 16:10
# Example: 1280x720 = 1.778 = 16:9

NOHD_OPTS="-aspect 16:10"

# Options for normal and lowres videos: use XV forcing 16x10
LOW_OPTS="-aspect 16:10 -vo xv"

VWIDTH=$($MPLAYER -identify -vo vdpau -frames 0 "$FILE" | grep ID_VIDEO_WIDTH | cut -c 16-25)
VCODEC=$($MPLAYER -identify -vo vdpau -frames 0 "$FILE" | grep ID_VIDEO_CODEC | cut -c 16-25)

# all following echo commands can be uncommented for debug info
#echo .
#echo " DEBUG info: video codec: $VCODEC"
#echo " DEBUG info: video width: $VWIDTH"
#echo " Debug info: 


# Test for codec, if it's supported by VDPAU, set options to use it. Then, check if the video is in HD,
# and if it's not, set non-HD options.
case $VCODEC in
ffh264) 
        #echo -e "Playing h.264 file $FILE:\n"
        MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffh264vdpau"
        if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
        fi
        if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
        fi
        ;;
ffmpeg2)
        #echo -e "Playing MPEG2 file $FILE:\n"
        MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffmpeg12vdpau"
        if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
        fi
        if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
        fi
        ;;
ffwmv3)
        #echo -e "Playing WMV3 file $FILE:\n"
        MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffwmv3vdpau"
        if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
        fi
        if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
        fi
        ;;
# VC-1 is largely unsupported by nvidia - uncomment this section if you're sure your card supports it.
ffvc1)
        #echo -e "Playing VC-1 file $FILE:\n"
        MPLAYEROPTS="$BASIC_OPTS -vo vdpau -vc ffvc1vdpau"
        if [ $VWIDTH -lt 1280 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$MPLAYEROPTS $NOHD_OPTS"
        fi
        if [ $VWIDTH -lt 700 ] && [ $VWIDTH != 0 ]; then
                MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
        fi
        ;;
*)
        #echo -e "Playing normal file $FILE:\n"
        # Use XV and yadif filter with 'normal' (DiVX, XViD, old WMV, etc.) files, and force 16:9
        # -vf filters only seem to work with XV, or at least they don't work w/VDPAU
        MPLAYEROPTS="$BASIC_OPTS $LOW_OPTS"
        ;;
esac

echo $MPLAYEROPTS

# 2  
Old 03-16-2009
can't you quote the path with spaces?

$ ./mplayer-resumer-vdpau.pl '/media/D/New CD/Test.mkv'
# 3  
Old 03-16-2009
It gave the same error... it must be something in how the perl script is calling the bash script because the bash script works just fine in dirs with and without spaces....
# 4  
Old 03-16-2009
did you try double-quotes?

$ ./mplayer-resumer-vdpau.pl "/media/D/New CD/Test.mkv"

that should work on Windows
# 5  
Old 03-16-2009
Yeah, single or double quotes... I'm sure it's something in the perl code
# 6  
Old 03-16-2009
assuming this is the line in the perl code that is problematic:

my $mplayeropts=`./vdpau-detector $infile`; chomp $mplayeropts;

try putting quotes around $infile (assuming that is the variable with the space):

my $mplayeropts=`./vdpau-detector \"$infile\"`; chomp $mplayeropts;

you can experiment with the type of quotes or adding an escape before the quotes: \"
# 7  
Old 03-17-2009
Thanks for the suggestion, but no go Smilie
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Iterate over `dirs` in a bash script

I would like to iterate over `dirs`in a script, but the script will never show more than one (current) folder #! /bin/bash for i in `dirs` do echo ${i} done echo ++++++++++++++++++ for i in $( dirs -p ) do echo ${i} done echo ------------------ dirscontent=`dirs` echo... (5 Replies)
Discussion started by: alexanderb
5 Replies

2. Shell Programming and Scripting

Dealing with filename spaces in Perl

The following command to replace text in place in multiple files in a directory is tripping up on filename spaces (Windows environment). I really don't know Perl. find '\\server\directory' | xargs perl -pi -e 's/textA/textB/g'Mike (2 Replies)
Discussion started by: Michael Stora
2 Replies

3. Shell Programming and Scripting

Perl : Arrays : where are these spaces coming from

Example data The sub and array in question sub parse_status { my $status_info = shift; my @info; push @info,"$1\n" if $status_info =~ /(System State : +)/; push @info, "System_Uptime : $1\n" if $status_info =~ /Uptime:.+?up (.+?), load/; push @info, "$1\n" if $status_info =~... (2 Replies)
Discussion started by: popeye
2 Replies

4. Shell Programming and Scripting

PERL : Remove spaces in a variable

I have a variable I want to remove the spaces in between. The output should be How can this be done Any help will be appreciated. Thanks in advance (1 Reply)
Discussion started by: irudayaraj
1 Replies

5. UNIX for Dummies Questions & Answers

**HELP** how to do a listing of dirs and all sub dirs only

I am trying to get a listing of ALL directories only under /export (as an example). I can get all the dirs directly under /export but I need any sub dirs under those dirs. I've looked (here and google) but can not find anything that works (4 Replies)
Discussion started by: bbraml
4 Replies

6. Shell Programming and Scripting

Not correct processing of “\ “ in names of dirs inside shell script (tar command - system backup scr

Hello, Recently, I've started with shell scripting, and decided to write a script for my system backup using tar. When I was dealing with tar execution inside shell script I found this, inside shell we have the following code: tar $TAR_PARAMS $ARCHIVE_FILE $EXCLUDE $BACKUP_STARTwith... (6 Replies)
Discussion started by: ilnar
6 Replies

7. UNIX for Advanced & Expert Users

script to recursively change permissions on file and dirs differently?

Hi there, I need to change all files/dirs 1. all files with 744 2. all dirs with 755 is there a script for that ? thanks, thegunman (13 Replies)
Discussion started by: TheGunMan
13 Replies

8. Shell Programming and Scripting

Removing leading and trailing spaces only in PERL

Hi All, I have a file with the following contents with multiple lines 172445957| 000005911|8| 400 Peninsula Ave.#1551 | And,K |935172445957|000005911 607573888 |000098536 | 2|Ane, B |J |Ane |1868 |19861206|20090106|20071001 I want to trim the "leading and trailing spaces only" from... (2 Replies)
Discussion started by: kumar04
2 Replies

9. Shell Programming and Scripting

script find files in two dirs HELP

I have a directory which is /home/mark/files/ , inside this particular I have a bunch of filles (see examples below) TST_SHU_00014460_20090302.txt TST_SHU_00016047_20090302.txt TST_SHU_00007838_20090303.txt TST_SHU_00056485_20090303.txt TST_SHU_00014460_20090303.txt... (2 Replies)
Discussion started by: fierusbentus
2 Replies

10. Shell Programming and Scripting

shell script to create dirs

hi, I would like to know of a shell script to create the following A script which will take in two parameters i.e. name of file and SID and create directories named /opt/oracle/admin/$SID/{bdump,cdump,udump}. Then edit the init file and change the three lines that look like this. ... (2 Replies)
Discussion started by: sjajimi
2 Replies
Login or Register to Ask a Question