743

I've renamed some files in a fairly large project and want to remove the .pyc files they've left behind. I tried the bash script:

 rm -r *.pyc

But that doesn't recurse through the folders as I thought it would. What am I doing wrong?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Teifion
  • 108,121
  • 75
  • 161
  • 195
  • 12
    It doesn't work because in UNIX, globs are expanded by the shell, not by the program being run. If you have a.pyc and b.pyc in the current directory, and directories foo and bar, `rm` will be called with arguments [-r, a.pyc, b.pyc]. – ephemient Apr 24 '09 at 19:34
  • 2
    if you are worrying about pushing your code to other people, you can just add it to the .gitignore `**/*.pyc` then you won't have to worry about it again – bubakazouba Jul 02 '15 at 17:18

25 Answers25

1290
find . -name "*.pyc" -exec rm -f {} \;
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • I tested both of these. The directories were probably too small to be significant, but this came out faster than mine, which is what I expected since mine has to assemble the list and then iterate through it, while yours removes each item as it is found. – Chris Lutz Apr 24 '09 at 12:25
  • 438
    Find has a builtin "-delete" action, so you could do just `find . -name \*.pyc -delete` – Christoffer May 29 '09 at 11:48
  • 58
    Most importantly, if this is a dev machine, you can set PYTHONDONTWRITEBYTECODE=True, and you'll never need to do this again. See: [this answer](http://stackoverflow.com/questions/154443/how-to-avoid-pyc-files/154617#154617). – mlissner May 30 '11 at 00:46
  • 5
    You are not quoting `{}`. What would happen if accidentally word-split and deleted an intermediate path which happens to be called like a fragment of the path you found? – Robottinosino Apr 03 '13 at 02:58
  • in my .bashrc: `alias rmPyCrap="find . -name \*.pyc -delete && find . -type d -name __pycache__ -delete"` – floer32 Jul 18 '13 at 13:38
  • 22
    `-delete` is not part of the POSIX specification, and not guaranteed to exist in all implementations of `find`. – chepner Aug 16 '13 at 12:13
  • 8
    If you are scared - which might be good - make a first pass with -exec echo {}, or - if you are *very* scared - use rm -i {} which ask you each time or rm - v {} so you see what you delete. – Yano Mar 18 '14 at 18:53
  • Just confirming this worked for me on Mac OSX mavericks. – Eric Hepperle - CodeSlayer2010 Nov 18 '14 at 19:11
  • Where can I set PYTHONDONTWRITEBYTECODE? Is there some kind of file I can edit? – Daniel Tate Aug 25 '16 at 08:25
  • when deleting many files, this command may have an issue.. especially when memory on the machine that you are running the command on is low. Andy Baker's answer is much better. – kapad Jan 22 '20 at 12:44
1070

find . -name '*.pyc' -type f -delete

Surely the simplest.

redseven
  • 849
  • 6
  • 11
Andy Baker
  • 21,158
  • 12
  • 58
  • 71
96

Add to your ~/.bashrc:

pyclean () {
        find . -type f -name "*.py[co]" -delete
        find . -type d -name "__pycache__" -delete
}

This removes all .pyc and .pyo files, and __pycache__ directories. It's also very fast.

Usage is simply:

$ cd /path/to/directory
$ pyclean
Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192
  • `find . -type d -name "__pycache__" -delete` will often give a warning about a missing path because apparently the contents will be added to the queue before the folder is deleted. `2>/dev/null` should fix that. – Mad Physicist Jan 20 '16 at 19:35
88

In current version of debian you have pyclean script which is in python-minimal package.

Usage is simple:

pyclean .
jb.
  • 23,300
  • 18
  • 98
  • 136
  • 36
    It's worth noting that pyclean appears to only delete .pyc files for which there is a corresponding .py file (at least on my system - ubuntu 12.10.) This means it's not very helpful in situations where a source file has been deleted and you want to clean up the leftover .pyc files. – tigerFinch Jul 08 '13 at 13:56
  • 1
    @holms `pyclean` (and now [`py3clean`](http://packages.ubuntu.com/wily/python3-minimal)) originate in a Debian package, and thus aren’t in RHEL. – duozmo Jan 09 '16 at 18:53
  • 1
    The `pyclean` command is now available as a Python package [installable from PyPI](https://pypi.org/project/pyclean/), which work cross-platform (including RHEL, macOS and Windows). It deletes any `.pyc` file w/o special preference as of today. – Peterino Dec 20 '20 at 20:58
53

If you're using bash >=4.0 (or zsh)

rm **/*.pyc

Note that */*.pyc selects all .pyc files in the immediate first-level subdirectories while **/*.pyc recursively scans the whole directory tree. As an example, foo/bar/qux.pyc will be deleted by rm **/*.pyc but not by */*.pyc.

The globstar shell options must be enabled. To enable globstar:

shopt -s globstar

and to check its status:

shopt globstar
Asclepius
  • 57,944
  • 17
  • 167
  • 143
d0k
  • 2,605
  • 19
  • 16
  • 1
    What's the difference in running `rm **/*.pyc` vs `rm */*.pyc`? (The latter seemed to work for me locally.) – Taylor D. Edmiston May 28 '15 at 17:25
  • 1
    @TaylorEdmiston `rm */*.pyc` will delete all `.pyc` files in all subdirectories of depth 1. `rm **/*.pyc` will delete all `.pyc` files in all subdirectories of depth 0+ – Adam Stewart Jun 22 '17 at 19:53
  • 1
    @AdamStewart Thanks for adding this. For others stumbling on this thread, the issue I was experiencing was that Apple's bash shipped with OS X doesn't include globstar (so `**` acts as `*` when run instead and running `shopt globstar` throws an error). – Taylor D. Edmiston Jun 22 '17 at 21:17
35

For windows users:

del /S *.pyc
haki
  • 9,389
  • 15
  • 62
  • 110
30

I used to use an alias for that:

$ which pycclean

pycclean is aliased to `find . -name "*.pyc" | xargs -I {} rm -v "{}"'
miku
  • 181,842
  • 47
  • 306
  • 310
  • 12
    In current debian it is pyclean. – jb. Dec 02 '12 at 11:16
  • 7
    This doesn't deal with whitespace in filenames well. You should use `find -print0` and `xargs -0` instead. – r3m0t Mar 12 '13 at 16:18
  • 2
    Why would you want to have python code with spaces in the file/folder names? Is that syntactically legal? – coredumperror Jul 07 '15 at 00:15
  • @CoreDumpError, yes, in fact on Windows Python installs to a directory with spaces ("Program Files"). – Paul Draper Jun 10 '18 at 16:13
  • The python interpreter may install there by default, but it's hardly a good place to put your *code*. Plus, you certainly wouldn't want the Program Files folder to be part of your package structure, which is why I was wary about syntax. – coredumperror Jun 10 '18 at 20:05
18
find . -name '*.pyc' -print0 | xargs -0 rm

The find recursively looks for *.pyc files. The xargs takes that list of names and sends it to rm. The -print0 and the -0 tell the two commands to seperate the filenames with null characters. This allows it to work correctly on file names containing spaces, and even a file name containing a new line.

The solution with -exec works, but it spins up a new copy of rm for every file. On a slow system or with a great many files, that'll take too long.

You could also add a couple more args:

find . -iname '*.pyc' -print0 | xargs -0 --no-run-if-empty  rm

iname adds case insensitivity, like *.PYC . The no-run-if-empty keeps you from getting an error from rm if you have no such files.

Ron Romero
  • 9,211
  • 8
  • 43
  • 64
16
$ find . -name '*.pyc' -delete

This is faster than

$ find . -name "*.pyc" -exec rm -rf {} \;
Moxdata
  • 160
  • 1
  • 4
15

Further, people usually want to remove all *.pyc, *.pyo files and __pycache__ directories recursively in the current directory.

Command:

find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
Mithril
  • 12,947
  • 18
  • 102
  • 153
  • This is a good answer, but a plain Python solution would be cross-platform and hence preferable. While, personally, I don't care about Windows probably half of the Python population lives on Windows -- and `find`, `grep` and friends don't work there. – Peterino Mar 14 '19 at 10:26
  • They do if you install the tooling. I'd recommend every windows CLI user do so to ease cross-compat: https://superuser.com/questions/168202/difference-between-unxutils-and-gnuwin32 – DylanYoung Apr 15 '20 at 19:02
11

Django Extension

Note: This answer is very specific to Django project that have already been using Django Extension.

python manage.py clean_pyc

The implementation can be viewed in its source code.

Yeo
  • 11,416
  • 6
  • 63
  • 90
8

Just to throw another variant into the mix, you can also use backquotes like this:

rm `find . -name *.pyc`
Clint Miller
  • 15,173
  • 4
  • 37
  • 39
  • 5
    This has the slight drawback of failing if there are too many matches, as there will be too many arguments to pass to `rm`. – chepner Jul 09 '12 at 13:23
7

full recursive

ll **/**/*.pyc
rm **/**/*.pyc
romuloigor
  • 182
  • 1
  • 11
  • Interesting, how does this compare to Andy and Bill's answers? – Austin Henley Oct 06 '12 at 21:55
  • 3
    One set of `**` is redundant, and as in `d0k`'s answer, you must have globstar enabled in bash 4+ for this to work as intended. i.e. do `shopt -s globstar` or have that in one of your sourced bash . files. – Reinstate Monica Please Jan 09 '14 at 17:53
  • 1
    Also `ll` is commonly aliased to something like `ls -l`, but isn't really a command or portable. So, to recursively list all `.pyc` files in `.`, you should instead do something like `echo **/*.pyc` with globstar enabled – Reinstate Monica Please Jan 09 '14 at 18:02
5

Now there is a package pyclean on PyPI, which is easy to use, and cross-platform. User just need a simple command line to clean all __pycache__ files in current dir:

pyclean .
mo-han
  • 397
  • 5
  • 5
4

if you don't want .pyc anymore you can use this single line in a terminal:

export PYTHONDONTWRITEBYTECODE=1

if you change your mind:

unset PYTHONDONTWRITEBYTECODE
Kevin Sabbe
  • 1,412
  • 16
  • 24
3

First run:

find . -type f -name "*.py[c|o]" -exec rm -f {} +

Then add:

export PYTHONDONTWRITEBYTECODE=1

To ~/.profile

Community
  • 1
  • 1
Michael Benin
  • 4,317
  • 2
  • 23
  • 15
2
find . -name "*.pyc"|xargs rm -rf
PiyusG
  • 1,157
  • 16
  • 28
2

If you want to delete all the .pyc files from the project folder.

First, you have

cd <path/to/the/folder>

then find all the .pyc file and delete.

find . -name \*.pyc -delete
Girish Vas
  • 680
  • 1
  • 10
  • 22
2

rm -r recurses into directories, but only the directories you give to rm. It will also delete those directories. One solution is:

for i in $( find . -name *.pyc )
do
  rm $i
done

find will find all *.pyc files recursively in the current directory, and the for loop will iterate through the list of files found, removing each one.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • This one works though I have to put it in a .sh file and run that (which is fine by me, I'll be using this command more than once) – Teifion Apr 24 '09 at 12:03
  • I believe putting it all on one line separated with ';'s should let you run it at the shell. But when I type that in bash, bash waits for the "done" at the end to execute anything... – Chris Lutz Apr 24 '09 at 12:08
  • That's an awful _antipattern_ (and a very common one too, I wish it could disappear): it breaks with filenames containing spaces or glob characters. And it misses the point of `find` with its `-exec` predicate: `find . -name '*.pyc' -exec rm {} +` (nicer, shorter, safer, robust, more efficient). – gniourf_gniourf Nov 15 '15 at 08:14
1

You can run find . -name "*.pyc" -type f -delete.

But use it with precaution. Run first find . -name "*.pyc" -type f to see exactly which files you will remove.

In addition, make sure that -delete is the last argument in your command. If you put it before the -name *.pyc argument, it will delete everything.

gpap
  • 2,394
  • 2
  • 9
  • 8
1

To delete all the python compiled files in current directory.

find . -name "__pycache__"|xargs rm -rf
find . -name "*.pyc"|xargs rm -rf
Abhishake Gupta
  • 2,939
  • 1
  • 25
  • 34
0

If you want remove all *.pyc files and __pycache__ directories recursively in the current directory:

  • with python:
import os

os.popen('find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf')
  • or manually with terminal or cmd:
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
Milovan Tomašević
  • 6,823
  • 1
  • 50
  • 42
0

py3clean works for me!

cd /usr/local/lib/python3.9
sudo py3clean -v .
Chance
  • 405
  • 4
  • 8
0

Had to add a few ignore params on M1:

pyclean --verbose . --ignore "Library",".Trash"  
Fawaz
  • 3,404
  • 3
  • 17
  • 22
0

DEL /F /S /Q "Z:\aaa\*.pyc"
use cmd, or save in bat file, in window

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 12 '23 at 14:59