2

I am new to python. I am trying to execute a bash script in python to extract the count of different file extensions. I tried the following command

import subprocess
output = subprocess.check_output("sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 ":" $1}'", shell=True)

But it throws a syntax error. On executing find command in bash shell

sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 ":" $1}'

output will be as follows

png:3156
json:333
c:282
svg:241
zsh:233
js:192
gz:169
zsh-theme:143
ttf:107
cache:103
md:93

So how can i get the same output in python code? what is the correction required in my current approach? Thanks in advance

10
  • 2
    use triple quotes on the outside like """sudo..."""? Commented Oct 6, 2017 at 12:36
  • 1
    The awk part should be something like awk '{print \"{\" $2 \":\" $1 \"}\"}'. It seems like you got unescaped double quotes inside double quotes. Commented Oct 6, 2017 at 12:36
  • File "<stdin>", line 1 direct_output = subprocess.check_output("sudo find . -type f -name '.' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print "{" $2 ":" $1 "}"}'", shell=True) ^ SyntaxError: invalid syntax Commented Oct 6, 2017 at 12:38
  • does the error still occurs without "sudo" ? Commented Oct 6, 2017 at 12:49
  • @GuillaumePaniagua: yes no difference by removing 'sudo' Commented Oct 6, 2017 at 12:50

2 Answers 2

4

As mentioned in the comments any double quote in a string quoted with double quotes needs to be escaped with a backslash:

import subprocess
output = subprocess.check_output("sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 \":\" $1}'", shell=True)

Single quotes inside a double quoted string do not have any special meaning (except directly at the beginning), so that doesn't allow you to avoid escaping.

The fine details are explained under the header String and Bytes literals from the Python language reference.

As mentioned in the comments another option, which is probably easier to read, is to use triple double quotes:

import subprocess
output = subprocess.check_output("""sudo find . -type f -name '*.*' -exec sh -c 'echo ${0##*.}' {} \; | sort | uniq -c | sort -nr | awk '{print $2 ":" $1}'""", shell=True)

While this answers the question, for ease of reading and maintainability I suggest to replace it instead completely with Python, as suggested in another answer.

Sign up to request clarification or add additional context in comments.

1 Comment

You are awesome!!
3

By the way, you could try to do the same thing in pure Python. Here is a minimal code that does it:

import os

def count_all_ext ( path ):
    res = {}
    for root,dirs,files in os.walk( path ):
        for f in files :
            if '.' in f :
                e = f.rsplit('.',1)[1]
                res[e] = res.setdefault(e,0)+1
    return res.items()


print '\n'.join( '%s:%d'%i for i in count_all_ext('.'))

OK, it's very long compared to the Bash snippet, but it's Python...

7 Comments

Thanks @Captain'Falm ..... Was expecting bash script to run in python!!
Yep, sorry... it's strong than me, I always try to script in python (instead of platform dependant shell)
I'd certainly consider this a better approach than the amalgam of tools glued together badly. (Clarifying "badly" -- properly used, awk could do the job of sort and uniq and the shells running the parameter expansion, etc; using 5 independent pieces instead of one is a sign of not knowing how to use the one well).
@CharlesDuffy Thanks for helping in deciding proper approach !!
@Captain'Flam: since bash asking super user privilege python approach is working fine!! As i am new to python i was unable to understand the line: print '\n'.join( '%s:%d'%i for i in count_all_ext('.')) please explain join method here!,Thanks in advance
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.