michael
michael

Reputation: 110650

How can I execute shell command with a | pipe in it

I am using python's subprocess call() to execute shell command. It works for a single command. But what if my shell command calls a command and pipe it to another command.

I.e. how can I execute this in python script?

grep -r PASSED *.log | sort -u | wc -l

I am trying to use the Popen way, but i always get 0 as output

p1 = subprocess.Popen(("xxd -p " + filename).split(), stdout=subprocess.PIPE)
p2 = subprocess.Popen("tr -d \'\\n\'".split(), stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(("grep -c \'"+search_str + "\'").split(), stdin=p2.stdout, stdout=subprocess.PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
p2.stdout.close()  # Allow p2 to receive a SIGPIPE if p3 exits.
output = p3.communicate()[0]

When I try the command in shell,it returns 1

 xxd -p file_0_4.bin | tr -d '\n'  | grep -c 'f5dfddd239'

I always get 0. Even if I get 1 when I type the same command at shell.

Upvotes: 8

Views: 4795

Answers (3)

falsetru
falsetru

Reputation: 369424

Call with shell=True argument. For example,

import subprocess

subprocess.call('grep -r PASSED *.log | sort -u | wc -l', shell=True)

Hard way

import glob
import subprocess

grep = subprocess.Popen(['grep', '-r', 'PASSED'] + glob.glob('*.log'), stdout=subprocess.PIPE)
sort = subprocess.Popen(['sort', '-u'], stdin=grep.stdout, stdout=subprocess.PIPE)
exit_status = subprocess.call(['wc', '-l'], stdin=sort.stdout)

See Replacing shell pipeline.

Upvotes: 23

shx2
shx2

Reputation: 64368

The other answers would work. But here's a more elegant approach, IMO, which is to use plumbum.

from plumbum.cmd import grep, sort, wc
cmd = grep['-r']['PASSED']['*.log'] | sort['-u'] | wc['-l']  # construct the command
print cmd() # run the command

Upvotes: 4

Udo Klein
Udo Klein

Reputation: 6912

You might want to look here or here That is use "subprocess" with shell=True

Upvotes: 0

Related Questions