You are not logged in.
Pages: 1
I like using programs that others have already written. I like automating things. Hence I often need to call programs from within other programs, and this often means going through some sort of subshell. I don't know how to safely construct the string that the shell is supposed to execute.
Suppose I need to call something of the form
program arg1 arg2
Any of "program", "arg1" and "arg2" may contain shell metacharacters. I need to know 1. which character(s) the shell uses to separate the tokens, so as to "escape" those characters if they occur in "program", "arg1" or "arg2", and 2. which other characters the shell gives special meaning to, so as to escape them too.
Is there a way to query a shell for metacharacters and token separators? I'd like to write things that work no matter which shell they are run in. Or is there some sort of zealously maintained library that keeps track of various shells and their caprices? I like to write my scripts in perl.
Offline
I think you are looking for the "qx" function in perl (quote-execute). Read about it here http://perldoc.perl.org/perlop.html#Quo … -Operators
Offline
Btw, both C and perl (and probably most others) use /bin/sh when they invoke shell commands. So there is no need to think about different shells, just use standard sh syntax. At least I think this is how it works
Offline
Thanks, the "perlop" page gave me a link to "perlsec" which gave me a link to "exec" which gave me a link to "system" which is what I want to use.
$res = system($program, $arg1, $arg2);
Basically "system" forks and calls execvp(3), which is a frontend to execve(2) except it expands its first argument according to $PATH. execve(2) executes a program with the given arguments. No shell is involved, so I don't need to escape anything!
It was pretty useless to be worried for such a trivial script (see below), but this issue popped up a lot whenever I was writing something. I'll know what to do now!
#!/usr/bin/env perl
my $music_library = "/all/mus";
use strict;
use File::Path;
for my $zip (@ARGV) {
if($zip =~ /([^-]+) - (.+) -- Jamendo/) {
my($artist, $album) = ($1, $2);
$artist =~ s/\//\\\//g;
$album =~ s/\//\\\//g;
my $path = "$music_library/$artist/$album";
mkpath $path;
if(system('7z', 'x', "$zip", "-o$path") == 0) {
unlink $zip;
} else {
warn "error while handling '$zip': $!"
}
} else {
warn "not smart enough to process this file: '$zip'."
}
}
Thanks again!
Last edited by peets (2008-06-06 21:10:15)
Offline
Pages: 1