Check if a command is valid

Grant Edwards invalid at invalid.invalid
Wed Jul 14 16:54:22 EDT 2010


On 2010-07-14, Steven W. Orr <steveo at syslang.net> wrote:
> On 07/12/10 21:29, quoth Kenny Meyer:
>
>> I have to figure out if a string is callable on a Linux system. I'm
>> actually doing this:
>> 
>>     def is_valid_command(command):
>>         retcode = 100 # initialize
>>         if command:
>>             retcode = subprocess.call(command, shell=True)
>>         if retcode is 0:
>>             print "Valid command."
>>         else:
>>             print "Looks not so good..."
>> 
>>     is_valid_command("ls")
>> 
>> Never mind the code, because this is not the original. The side
>> effect of subprocess.call() is that it *actually* executes it, but I
>> just need the return code. What are better ways of doing this?
>
> Luke! Use the force!
>
> #! /usr/bin/python
>
> import os
> def is_valid_command(command):
>     looking_good = False
>     for ii in os.environ['PATH'].split(':'):
>         if os.access(ii + '/' + command, os.X_OK):
>             looking_good = True
>             break
>     print ["Looks not so good...", "Valid command."][looking_good]
>
> is_valid_command('python')
> is_valid_command('pythoon')

Just to be clear, that's not the same as the OP's code in two
respects:

 1) It doesn't handle shell builtins or aliases.

 2) It determines not whether a command is valid (returns 0), but
    whether a command exists as an executable.  "Valid" is a rather
    small subset of "exists".

Of course the OP didn't explain what he meant by "callable", so all we
have to go on is his posted code.
   
> This way you don't start up any subprocesses and you are actually
> doing what the shell would do for you.
>
> THE ONLY DIFFERENCE is that a persistent bash would hash all of the
> contents of what lives in PATH and so might have a slight shot of
> being faster under somewhat obscure conditions.

No, there are other differences.  See above.

> I would strongly encourage you to not execute an arbitrary string to
> see if it returns a pretty return code.
>
> is_valid_command('{cd /; rm -rf /}')
>
> Warning:

> * It only checks if the command exists in PATH and is executable TO
>   YOU:

Which is different than determining whether a command (including
arguments) is valid (callable and returns 0).  However, running a
command to determine if it's valid is going to cause problems sooner
or later due to side-effects of that command.

For example, the first time you the command "rm /path/to/a/file" it
may be valid, but the second time it won't be.

> * Do not make fun of is_valid_command. It will get angry.

And don't taunt happy fun ball!

> * You might also want to beef it up a la
>         pp = ii + '/' + command
>         if os.access(pp, (os.X_OK) and not os.stat.isdir(p)):
> so you are checking executable files and not directories etc...
> * More warnings can be amplified upon over pitchers of beer.


-- 
Grant Edwards               grant.b.edwards        Yow! My mind is making
                                  at               ashtrays in Dayton ...
                              gmail.com            



More information about the Python-list mailing list