tags:

views:

97

answers:

5

So, I have a bash script inside of which I'd like to have a conditional which depends on what a perl script returns. The idea behind my code is as follows:

for i in $(ls); do
    if $(perl -e "if (\$i =~ /^.*(bleh|blah|bluh)/) {print 'true';}"); then
       echo $i;
   fi;
done

Currently, this always returns true, and when I tried it with [[]] around the if statement, I got errors. Any ideas anyone?

P.s. I know I can do this with grep, but it's just an example. I'd like to know how to have Bash use Perl output in general

P.p.s I know I can do this in two lines, setting the perl output to a variable and then testing for that variables value, but I'd rather avoid using that extra variable if possible. Seems wasteful.

+1  A: 

The return value of the previous command is stored in the bash variable $?. You can do something like:

perl someargs script.pl more args
if [ $? == 0 ] ; then
    echo true
else
    echo false
fi
Matt Kane
His perl code always exits 0 currently, so you'll always show true.
Daenyth
+8  A: 

If you use exit, you can just use an if directly. E.g.

if perl -e "exit 0 if (successful); exit 1"; then
   echo $i;
fi;

0 is success, non-zero is failure, and 0 is the default if you don't call exit.

Matthew Flaschen
This will always exit 0.
Daenyth
@Daenyth, it wasn't supposed to be a complete example. But I've changed it so it can return 1.
Matthew Flaschen
@Matthew: There's still no reason to use perl here though. See my answer
Daenyth
@Daenyth, read the question: "I'd like to know how to have Bash use Perl output in general"
Matthew Flaschen
Sweet, this is exactly what I wanted. Thanks!
Eli
+3  A: 

To answer your question, you want perl to exit 1 for failure and exit 0 for success. That being said, you're doing this the wrong way. Really. Also, don't parse the output of ls. You'll cause yourself many headaches.

for file in *; do
    if [[ $file = *bl[eau]h ]]; then 
        echo "$file matches"
    fi
done
Daenyth
+1  A: 

It's a good question, my advice is: keep it simple and go Posix (avoid Bashisms1) where possible..

so ross$ if perl -e 'exit 0'; then echo Good; else echo Bad; fi
Good
so ross$ if perl -e 'exit 1'; then echo Good; else echo Bad; fi
Bad

1. Sure, the OP was tagged bash, but others may want to know the generic-Posix form.

DigitalRoss
+3  A: 
for file in * ; do
    perl -e "shift =~ /^.*(bleh|blah|bluh)/ || exit 1" "$file" && echo $file: true
done

You should never parse the output of ls. You will have, at least, problems with file names containing spaces. Plus, why bother when your shell can glob on its own?

Quoting $file when passing to the perl script avoids problems with spaces in file names (and other special characters). Internally I avoided expanding the bash $file variable so as to not run afoul of quoting problems if the file name contained ", ' or \

Perl seems to (for some reason) always return 0 if you don't exit with an explicit value, which seems weird to me. Since this is the case I test for failure inside the script and return nonzero in that case.

Sorpigal