BarJacks
BarJacks

Reputation: 129

Running bash command on server

I am trying to run the bash command pdfcrack in Python on a remote server. This is my code:

bashCommand = "pdfcrack -f pdf123.pdf > myoutput.txt"
import subprocess
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()

I, however, get the following error message:

Non-option argument myoutput2.txt
Error: file > not found

Can anybody see my mistake?

Upvotes: 0

Views: 191

Answers (3)

Jean-François Fabre
Jean-François Fabre

Reputation: 140256

> is interpreted by shell, but not valid otherwise.

So, that would work (don't split, use as-is):

process = subprocess.Popen(bashCommand, shell=True)

(and stdout=subprocess.PIPE isn't useful since all output is redirected to the output file)

But it could be better with native python for redirection to output file and passing arguments as list (handles quote protection if needed)

with open("myoutput.txt","w") as f:
    process = subprocess.Popen(["pdfcrack","-f","pdf123.pdf"], stdout=subprocess.PIPE)
    f.write(process.read())
    process.wait()

Upvotes: 1

chepner
chepner

Reputation: 531808

The first argument to Popen is a list containing the command name and its arguments. > is not an argument to the command, though; it is shell syntax. You could simply pass the entire line to Popen and instruct it to use the shell to execute it:

process = subprocess.Popen(bashCommand, shell=True)

(Note that since you are redirecting the output of the command to a file, though, there is no reason to set its standard output to a pipe, because there will be nothing to read.)

A better solution, though, is to let Python handle the redirection.

process = subprocess.Popen(['pdfcrack', '-f', 'pdf123.pdf'], stdout=subprocess.PIPE)
with open('myoutput.txt', 'w') as fh:
    for line in process.stdout:
        fh.write(line)
        # Do whatever else you want with line

Also, don't use str.split as a replacement for the shell's word splitting. A valid command line like pdfcrack -f "foo bar.pdf" would be split into the incorrect list ['pdfcrack', '-f', '"foo', 'bar.pdf"'], rather than the correct list ['pdfcrack', '-f', 'foo bar.pdf'].

Upvotes: 1

furas
furas

Reputation: 142814

Your mistake is > in command.

It doesn't treat this as redirection to file because normally bash does it and now you run it without using bash.

Try with shell=True if you whan to use bash. And then you don't have to split command into list.

subprocess.Popen("pdfcrack -f pdf123.pdf > myoutput.txt", shell=True)

Upvotes: 0

Related Questions