I have a python script that generates a number of shell commands from the given input. The problem is that when it tries to execute the generated commands, it fails, but when i run the generated commands myself (that is, from the command line), they are executed successfully.
Here is the generated command:
find /home/me/downloader/0-29/ -type f | grep -i .rpm$ | xargs -i cp {} /home/me/downloader/builds/0-29/
Here is the error message when it is run by the python script:
find: paths must precede expression: | Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
Could you help me understand what the problem is?
UPD: Here is the function i use for executing the generated commands:
def exec_command(command):
process = subprocess.Popen(command.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
return output
I believe what you do is you start a single program called
find
with many parameters, incl.|
andgrep
andxargs
- and these are not arguments to find.What you want to do is probably to ask bash to run
find
and then pipe the outcome togrep
, etc. One way to do that is to execute a single command calledbash
with two parameters (-c
) and a whole string incl. piped commands, e.g.Since your command is a pipeline, you must set
shell=True
so that subprocess will send the command, as is, to the shell:Or,
Also, do not do splitting in python on a command with a pipeline. This will result in
find
being passed|
as one of its arguments instead of as a shell operator.It also appears that the command can be simplified:
Since the above is no longer a pipeline, it could, with a minor modification, be split and given to subprocess with shell=False. The modification is that the single-quotes around
'*.rpm'
are there to protect the glob from shell expansion. With shell=False, the shell doesn't remove them. So, we have to. For shell=False and for use withcommand.split()
: