Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

shell

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.

like image 892
michael Avatar asked Aug 05 '13 05:08

michael


People also ask

What is $? In shell script?

$? is used to find the return value of the last executed command. Try the following in the shell: ls somefile echo $?

How do you execute a command in a variable in shell script?

Here, the first line of the script i.e. “#!/bin/bash” shows that this file is in fact a Bash file. Then we have created a variable named “test” and have assigned it the value “$(echo “Hi there!”)”. Whenever you want to store the command in a variable, you have to type that command preceded by a “$” symbol.

What happens when you type a command in shell?

When you enter a command, the first thing the shell does is break the entire command into "tokens." The shell will then look for a program name belonging to the first token in the command line.


2 Answers

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.

like image 116
falsetru Avatar answered Oct 14 '22 08:10

falsetru


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
like image 40
shx2 Avatar answered Oct 14 '22 09:10

shx2