3

I want to run a bash script from a python program. The script has a command like this:

find . -type d -exec bash -c 'cd "$0" && gunzip -c *.gz | cut -f 3 >> ../mydoc.txt' {} \;

Normally I would run a subprocess call like:

subprocess.call('ls | wc -l', shell=True)

But that's not possible here because of the quoting signs. Any suggestions?

Thanks!

  • 5
    Can you escape the `' ` marks with a `\ `? – ifconfig Aug 15 '17 at 16:40
  • Wow. It actually does work. I didn't think it would work since the other command is going in each subdirectories. Thanks! –  Aug 15 '17 at 16:45
  • Possible duplicate of [why are '(single quote) or "(double quote) not allowed in subprocess.check\_output() in python?](https://stackoverflow.com/questions/22224800/why-are-single-quote-or-double-quote-not-allowed-in-subprocess-check-outpu) – agtoever Aug 15 '17 at 16:46

3 Answers3

3

While the question is answered already, I'll still jump in because I assume that you want to execute that bash script because you do not have the functionally equivalent Python code (which is lees than 40 lines basically, see below). Why do this instead the bash script?

  • Your script now is able to run on any OS that has a Python interpreter
  • The functionality is a lot easier to read and understand
  • If you need anything special, it is always easier to adapt your own code
  • More Pythonic :-)

Please bear in mind that is (as your bash script) without any kind of error checking and the output file is a global variable, but that can be changed easily.

import gzip
import os

# create out output file
outfile = open('/tmp/output.txt', mode='w', encoding='utf-8')

def process_line(line):
    """
    get the third column (delimiter is tab char) and write to output file
    """
    columns = line.split('\t')
    if len(columns) > 3:
        outfile.write(columns[3] + '\n')

def process_zipfile(filename):
    """
    read zip file content (we assume text) and split into lines for processing
    """
    print('Reading {0} ...'.format(filename))
    with gzip.open(filename, mode='rb') as f:
        lines = f.read().decode('utf-8').split('\n')
        for line in lines:
            process_line(line.strip())


def process_directory(dirtuple):
    """
    loop thru the list of files in that directory and process any .gz file
    """
    print('Processing {0} ...'.format(dirtuple[0]))
    for filename in dirtuple[2]:
        if filename.endswith('.gz'):
            process_zipfile(os.path.join(dirtuple[0], filename))

# walk the directory tree from current directory downward
for dirtuple in os.walk('.'):
    process_directory(dirtuple)

outfile.close()
Arminius
  • 1,029
  • 7
  • 11
2

Escape the ' marks with a \.

i.e. For every: ', replace with: \'

ifconfig
  • 6,242
  • 7
  • 41
  • 65
2

Triple quotes or triple double quotes ('''some string''' or """some other string""") are handy as well. See here (yeah, its python3 documentation, but it all works 100% in python2)

mystring = """how many 'cakes' can you "deliver"?"""
print(mystring)
how many 'cakes' can you "deliver"?
Leobuilt
  • 36
  • 3