-1

We have python version - 2.7.5 on my Linux machine - redhat 7.3

I write this simple script in order to use sed to replace string in file

more  test.py
#!/usr/bin/env python


import subprocess
subprocess.call("sed s'/2.6/2.6.4/g' /tmp/file.xml")

but we got

Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    subprocess.call("sed s'/2.6/2.6.4/g' /tmp/file.xml")
  File "/usr/lib64/python2.7/subprocess.py", line 524, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

what is wrong with the python script ?

 more file.xml

 2.6.0.3-8
1

In Python:

when using

args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.
...
If shell is True, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user’s home directory.

So, your approach will work when specifying:

subprocess.call("sed s'/2\.6/2.6.4/g' /tmp/file.xml", shell=True)

But ...

Warning: Using shell=True can be a security hazard.
Executing shell commands that incorporate unsanitized input from an untrusted source makes a program vulnerable to shell injection, a serious security flaw which can result in arbitrary command execution. For this reason, the use of shell=True is strongly discouraged in cases where the command string is constructed from external input.

When using shell=True, pipes.quote() can be used to properly escape whitespace and shell metacharacters in strings that are going to be used to construct shell commands.

Conclusion: when passing args (i.e. command) as a single string (with shell=True being set) you should at least escape/quote it. But, as mentioned above, providing a sequence of arguments is highly preferred:

import subprocess

subprocess.call(['sed', 's/2\.6/2.6.4/g', '/tmp/file.xml'])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.