MaikoID
MaikoID

Reputation: 4987

How to handle quotes in Perl when calling system commands?

I'm trying to make a very simple script to call the PDFXchange viewer from a .desktop file. But I'm not able to do this because the bash is seeing things that I'm not aware:

#!/usr/bin/perl

use strict;
use warnings;

my $winepath = `winepath -w -0 "$ARGV[0]"`;

my $cmd=join ' ',
    'wine',
    '\'C:\Program Files\Tracker Software\PDF Viewer\PDFXCview.exe\'',
    "\'$winepath\'";

print $cmd . "\\n";

exec $cmd;

Output

$ exec_pdfxcv 'pdf with spaces.pdf' 
wine 'C:\Program Files\Tracker Software\PDF Viewer\PDFXCview.exe' 'Z:\media\FILES\pdf with spaces.pdf'\nsh: 1: Syntax error: Unterminated quoted string

I'm very beginner at Perl, so I run out of ideas very quickly after tried a couple of times with different quotes configurations.

Upvotes: 0

Views: 475

Answers (2)

zdim
zdim

Reputation: 66883

It seems that you dodged the bullet (of the common inscrutable mangle of quotes and escapes) here, since you don't need the shell for what is done and the rest doesn't need much either.

Then use the list-form of exec, which bypasses the shell altogether. This can be done with system as well but, alas, not with backticks.

my $winepath = `winepath -w -0 "$ARGV[0]"`;
chomp $winepath;

my @cmd = (
    'wine', 
    q('C:\Program Files\Tracker Software\PDF Viewer\PDFXCview.exe'),
    "'$winepath'"
); 
exec @cmd;

Note the use of the q() operator as single quotes, freeing the symbol ' for use inside.

We should remove the newline from $winepath (returned by qx) and need to protect spaces inside it by adding ' around it.

Going through the shell only makes it harder; do it only when you specifically need the shell.

Once you do need the shell, however, be aware of String::ShellQuote and Win32::ShellQuote.

Finally, work through Quoting the Shell from Perl.com. A required reading in my opinion.

Upvotes: 2

MaikoID
MaikoID

Reputation: 4987

I finally make it work after a hundred of tries.

#!/usr/bin/perl

use strict;
use warnings;

my $winepath = `winepath -w -0 "$ARGV[0]"`;

exec 'wine', q(C:\Program Files\Tracker Software\PDF Viewer\PDFXCview.exe), "".$winepath."";

I hope help someone!

If there is anyone interested in the .desktop file:

[Desktop Entry]
Name=PDF XChange Viwer
Comment=View multi-page documents
Exec=exec_pdfxcv %U
StartupNotify=true
Terminal=false
Type=Application
StartupWMClass=PDFXCview.exe
Icon=evince
Categories=GNOME;GTK;Office;Viewer;
MimeType=application/pdf;application/x-bzpdf;application/x-gzpdf;application/x-xzpdf;application/x-ext-pdf;application/postscript;application/x-bzpostscript;application/x-gzpostscript;image/x-eps;image/x-bzeps;image/x-gzeps;application/x-ext-ps;application/x-ext-eps;application/x-dvi;application/x-bzdvi;application/x-gzdvi;application/x-ext-dvi;image/vnd.djvu;image/vnd.djvu+multipage;application/x-ext-djv;application/x-ext-djvu;image/tiff;application/x-cbr;application/x-cbz;application/x-cb7;application/x-cbt;application/x-ext-cbr;application/x-ext-cbz;application/vnd.comicbook+zip;application/x-ext-cb7;application/x-ext-cbt;application/oxps;application/vnd.ms-xpsdocument;

Upvotes: 1

Related Questions