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
  • whoops, no. that was my comment from the run. removed, thanks. – tarabyte Apr 25 '18 at 17:22
  • Strange error. There is no -delete in your find invocation… – Kamil Maciorowski Apr 25 '18 at 20:51
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).

  • No, you're right, the error message doesn't look like it comes from find at all. – tripleee Apr 25 '18 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 '18 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 '18 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 '18 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.