4

There are lots of posts where people asking how to delete files except ones, but my question is more specific. There are several folders named migrations in current directory's sub-folders, which contain __init__.py file and some more. How to delete all files except __init__.py in all sub-folders named migrations from current folder?

UPD: And is it possible to overwrite __init__.py with empty file?

Folder structure:

├── folder_1
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-35.pyc
│   │       └── __init__.cpython-35.pyc
├── folder_2
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-35.pyc
│   │       └── __init__.cpython-35.pyc
├── folder_3
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-35.pyc
│   │       └── __init__.cpython-35.pyc
9
  • you mean that, if the init.py is outside a "migrations" folder, it can be deleted? Jun 9, 2016 at 2:52
  • @Vitor please check edited post, mb there are some bad grammar in my english, but I think it makes sense. Jun 9, 2016 at 2:58
  • just let us know the hierarchy of your directory structure so it will be more useful to solve your problem
    – Ankanna
    Jun 9, 2016 at 3:29
  • @JohnAnkanna check please updated post Jun 9, 2016 at 3:38
  • init.py are always inside "migrations", so you just loop into files. if the file is init.py empty it, if not delete it. Am I right? Jun 9, 2016 at 3:50

3 Answers 3

8

With find:

find . -path '*/migrations/__init__.py' -exec truncate -s 0 {} + -o -path '*/migrations/*' -delete

This runs find in the current directory (.), and:

  • for anything matching migrations/__init__.py, it will run the truncate command. truncate -s 0 <file> reduces the file to size 0 (empty);
  • failing that match, for anything matching migrations/*, it will delete it;
  • the * in -path matches / unlike the * in bash.

Example:

$ tree                                                                                                                                   
.
├── folder_1
│   └── migrations
│       ├── 0001_initial.py
│       ├── __init__.py
│       └── __pycache__
│           ├── 0001_initial.cpython-35.pyc
│           └── __init__.cpython-35.pyc
├── folder_2
│   └── migrations
│       ├── 0001_initial.py
│       ├── __init__.py
│       └── __pycache__
│           ├── 0001_initial.cpython-35.pyc
│           └── __init__.cpython-35.pyc
└── folder_3
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    └── migrations
        ├── 0001_initial.py
        ├── __init__.py
        └── __pycache__
            ├── 0001_initial.cpython-35.pyc
            └── __init__.cpython-35.pyc

9 directories, 15 files
$ find . -path '*/migrations/__init__.py' -exec truncate -s 0 {} + -o -path '*/migrations/*' -delete                
$ tree                                                                                              
.
├── folder_1
│   └── migrations
│       └── __init__.py
├── folder_2
│   └── migrations
│       └── __init__.py
└── folder_3
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    └── migrations
        └── __init__.py

6 directories, 6 files

$ wc -l */migrations/__init__.py
0 folder_1/migrations/__init__.py
0 folder_2/migrations/__init__.py
0 folder_3/migrations/__init__.py
0 total
4
  • Thanks, new command for me truncate. Jun 9, 2016 at 6:38
  • +1 Pro find usage, does -o only operate on anything which isn't matched the first expression? I can only find it in the examples section of the man page.
    – Arronical
    Jun 9, 2016 at 12:09
  • @Arronical yes, it's an OR. You can find it in the OPERATORS section of the manpage (right above STANDARDS CONFORMANCE). It's also part of POSIX.
    – muru
    Jun 9, 2016 at 14:32
  • Cheer @muru, my lazy eyes struck again!
    – Arronical
    Jun 9, 2016 at 14:34
2

Create a .py file, edit the path (directory that you will work), and compile it (python3).

  • code: delete all files on 'path' except 'target_file' inside 'target_folder', that are just clear(empty).
import os, sys
path='/home/vitor/Desktop/teste/'
target_folder='migrations'
target_file='__init__.py'

for directory, subdirs, files in os.walk(path):
    for file_name in files:
        folder_name=os.path.split(os.path.abspath(directory))[-1]
        if(folder_name==target_folder and file_name==target_file):
            open(directory+'/'+file_name, 'w').close()
        else:
            os.remove(directory+'/'+file_name)
2
  • Thanks for suggestion, but I'd like to have command line solution. I have already script in python which does this function, I upvoted your answer. Thanks for your effort. gist.github.com/MichaelPavlov/a1394fca9a4a0228a2dcc12427121f5a Jun 9, 2016 at 5:36
  • @МихаилПавлов just call the script from the command line? You can even pass command line arguments as target folder and target file.
    – Ajasja
    Jun 9, 2016 at 11:15
0

Here is a simpler command. I know some one already answered the question, but these commands should be simpler and unique. Try them to see if they work.

To remove every subfolder and file except __init__.py and displays which files have been deleted, try the following commands:

rm -rfv ./*/migrations/!(__init__.py)

To make a empty file, just add the following command in addition:

> ./*/migrations/__init__.py

The above command is just like writing empty data to a file like as follows:

/dev/null > ./*/migrations/__init__.py

Note

All these commands execute from current directory .

Precaution

Please make a backup before you try any of the commands. No one is 100% perfect in this world.

1
  • Your first command is almost certainly using an extended glob. Zsh?
    – muru
    Jun 9, 2016 at 14:00

You must log in to answer this question.

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