質問

For example, in /tmp I have files ending in .txt, .doc, and .jpg that I'd like to delete in one step using shred and subprocess.

The following does the job:

subprocess.call('bash -c "shred -n 5 -uz /tmp/{*.txt,*.pdf,*.doc}"', shell=True)

How would I do this command without using shell=True. I've tried the following:

subprocess.call(['bash', '-c', '"shred -n 10 -uz /tmp/{*.txt,*.pdf,*.doc}"'])
subprocess.call(['bash', '-c', 'shred', '-n 10', '-uz', '/tmp/{*.txt,*.pdf,*.doc}'])

Any suggestions?

役に立ちましたか?

解決

I believe that other guy is spot on (haven't tried it myself though). However if you ever find yourself having similar issues again shlex.split(s) might be helpful. It takes the string 's' and splits it "using shell-like syntax".

In [3]: shlex.split(s)
Out[3]: ['bash', '-c', 'shred -n 5 -uz /tmp/{*.txt,*.pdf,*.doc}']

他のヒント

subprocess.call(['bash', '-c', 'shred -n 10 -uz /tmp/{*.txt,*.pdf,*.doc}'])

You can tell how a command is expanded and split up with:

$ printf "Argument: %s\n" bash -c "shred -n 5 -uz /tmp/{*.txt,*.pdf,*.doc}"
Argument: bash
Argument: -c
Argument: shred -n 5 -uz /tmp/{*.txt,*.pdf,*.doc}

In the more general case (but overkill here), if you're ever in doubt of what's executed by something with which parameters, you can use strace:

$ cat script
import subprocess
subprocess.call('bash -c "shred -n 5 -uz /tmp/{*.txt,*.pdf,*.doc}"', shell=True)

$ strace -s 1000 -fe execve python script
...
execve("/bin/bash", ["bash", "-c", "shred -n 5 -uz /tmp/{*.txt,*.pdf,*.doc}"], [/* 49 vars */]) = 0
...
$ 

If the command is coming from a trusted source e.g., it is hardcoded then there is nothing wrong in using shell=True:

#!/usr/bin/env python
from subprocess import check_call

check_call("shred -n 10 -uz /tmp/{*.txt,*.pdf,*.doc}",
           shell=True, executable='/bin/bash')

/bin/bash is used to support {} inside the command.

This command doesn't run /bin/sh

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top