Issue
I want to check if a command exists on my machine (RedHat) inside a perl script.
Im trying to check if compgen -c
contains the desired command, but running it from inside a script just gives me an empty output. Other commands work fine.
example.pl:
my $x = `compgen -c`;
print $x;
# empty output
my $y = `ls -a`;
print $y;
# .
# ..
# example.pl
Are there possible solutions for this? Or is there a better way to check for commands on my machine?
Solution
First, Perl runs external commands using /bin/sh
, which is nowadays a link to a shell that is a default-of-sorts on your system. Much of the time that is bash
, but not always; on RedHat it is.
This compgen
is a bash builtin. One way to discover that is to run man compgen
(in bash) -- and the bash
manual pops up. Another way is type
as Dave shows.
To use builtins we generally need to run an explicit shell for them, and they have a varied behavior in regards to whether the shell is "interactive" or not.† I can't find a discussion of that in bash documentation for this builtin but experimentation reveals that you need
my @completions = qx(bash -c "compgen -c")
The quotes are needed so to pass a complete command to a shell that will be started.
Note that this way you don't catch any STDERR
out of those commands. That will come out on the terminal, and it can get missed that way. Or, you can redirect that stream in the command, by adding 2>&1
(redirect to STDOUT
) at the end of it.
This is one of the reasons to use one of a number of good libraries for running and managing external commands instead of the builtin "backticks" (the qx I use above is an operator form of it.)
† This can be facilitated with -i
my @output_lines = qx(bash -i -c "command with arguments")
Answered By - zdim Answer Checked By - Dawn Plyler (WPSolving Volunteer)