0

I want to delete all .pyc and .pyo files recursively but exclude a certain directory. I just ran into some limitation where find cannot delete when ignoring. I tried piping the result to xargs rm but that fails, too.

find . -not \( -path somedir -prune \) -name '*.py[co]' -exec rm '{}' \;

with error:

find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect.  If you want to carry on anyway, just explicitly use the -depth option.

This also fails:

find . -type f -not -path 'somdir/*' -name '*.py[co]' -print0 | xargs -0 rm

Versions:

  • OS: Ubuntu 14.04 LTS
  • find version 4.4.2
2
  • whoops, no. that was my comment from the run. removed, thanks.
    – tarabyte
    Apr 25, 2018 at 17:22
  • Strange error. There is no -delete in your find invocation… Apr 25, 2018 at 20:51

4 Answers 4

0

You seem to be confusing how -not and -prune interact. The usual thing is "find this and prune it, or this and prune it, or this and actually do something with it."

find . -path somedir -prune -o -name '*.py[co]' -delete

I replaced -exec ... with -delete which runs a built-in delete action with no external processes. If you want to -exec something else at some point, perhaps use -exec command {} + instead of -exec command {} \; (and notice how the single quotes around {} aren't really useful; the shell will process and remove them before find runs anyway).

4
  • No, you're right, the error message doesn't look like it comes from find at all.
    – tripleee
    Apr 25, 2018 at 7:34
  • that fails with error: find: The -delete action atomatically turns on -depth, but -prune does nothing when -depth is in effect. If you want to carry on anyway, just explicitly use the -depth option.
    – tarabyte
    Apr 25, 2018 at 20:45
  • both versions produce the same result, deleting files in somedir when i don't want to touch that dir.
    – tarabyte
    Apr 25, 2018 at 22:13
  • Can you reveal what exactly somedir corresponds to and how you identify it in the find command line? For example, find . -path .git -prune -o -ls prints stuff in ./.git/ but find . -path ./.git -prune -o -ls works as intended.
    – tripleee
    Apr 30, 2018 at 8:11
0

If "somedir" are not so many, you can remove the write permission temporarily and just -name '*.py[co]' -delete all of them.

Remember add the write permission back to "somedir".

Br,

0

Do the filtering with awk, and use xargs to run the command?

find . -type f -name '*.py[co]' -print0 \
    | awk -vRS='\0' '!/^.\/somedir\//' \
    | xargs -0 rm

awk parameters:

  • -vRS='\0' sets RS (Record Separator) to nul (\0) instead of the default (\n)
  • ! negates the regex
  • ^./somedir/ any record beginning with ./somedir/
    • don't forget to escape the regex / path slashes - raw regex becomes: ^.\/somedir\/
0

So it seems I needed to explicitly put the prefix of . in front of the directory. I'm not sure I completely understand why, but for anyone else in this situation:

Fails:

find . -type f -not -path 'somdir/*' -name '*.py[co]' -print0 | xargs -0 rm

Works:

find . -type f -not -path './somdir/*' -name '*.py[co]' -print0 | xargs -0 rm

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .