Question

I'm trying to run this BASH command in Popen:

find /tmp/mount -type f -name "*.rpmsave" -exec rm -f {} \;

But every time I get: "find: missing argument to `-exec'\n" in stderr.

What would the python equivalent of this be?

My naive aproach would be:

for (root,files,subdirs) in os.walk('/tmp/mount'):
    for file in files:
        if '.rpmsave' in file:
            os.remove(file)

surely there is a better, more pythonic way of doing this?

Was it helpful?

Solution

You've actually got two questions here — first, why your Popen construction doesn't work, and second, how to use os.walk properly. Ned answered the second one, so I'll address the first one: you need to be aware of shell escaping. The \; is an escaped ; since normally ; would be interpreted by Bash as separating two shell commands, and would not be passed to find. (In some other shells, {} must also be escaped.)

But with Popen you don't generally want to use a shell if you can avoid it. So, this should work:

import subprocess

subprocess.Popen(('find', '/tmp/mount', '-type', 'f',
                  '-name', '*.rpmsave', '-exec', 'rm', '-f', '{}', ';'))

OTHER TIPS

What you have is basically the way to do it. You have three different things you are coordinating: 1) walk the tree, 2) only operate on .rpmsave files, and 3) delete those files. Where would you find something that natively does all of that without having to spell it out? The Bash command and the Python code both have about the same complexity, which is not surprising.

But you have to fix your code, like this:

for root,files,subdirs in os.walk('/tmp/mount'):
    for file in files:
        if file.endswith('.rpmsave'):
            os.remove(os.path.join(root, file))

If you find yourself doing this stuff a lot. This could be a useful wrapper around os.walk:

def files(dir):
   # note you have subdirs and files flipped in your code
   for root,subdirs,files in os.walk(dir):
      for file in files:
         yield os.path.join(root,file)

To delete a bunch of files with a particular extension inside a directory:

[os.remove(file) for file in files(directory) if file.endswith('.extension')]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top