5

This type of question has been asked before, but I can't seem to get exactly what I want through the help I've found.

This question has an answer by user Iker, where the user gives code that does work exactly as intended: it removes all the files and directories from a folder, but not the parent folder itself.

I want to tweak this further by deleting all the files from a parent directory, but not the parent directory, and I want to exclude a folder within the directory.

The code I am using is:

import os
import shutil

files = '[the path to my folder]'

for root, dirs, files in os.walk(files):
    for f in files:
        os.unlink(os.path.join(root, f))
    for d in dirs:
        shutil.rmtree(os.path.join(root, d))

I have tried adding an "If" statement after the "for" statement that basically says:

if files != keep

and I have a variable "keep" pointing to a folder in the parent file called "keep," so that this script will delete everything except the parent directory and the directory called "keep" within the parent. However, after adding that, the code does not work.

Here is the exact code I had, with the if statement that breaks the code:

import os
import shutil

files = '[the path to the parent folder'
keep = '[the path to the "keep" folder]'

for root, dirs, files in os.walk(files):
    for f in files:
        if files != keep:
            os.unlink(os.path.join(root, f))
    for d in dirs:
        if files != keep:
            shutil.rmtree(os.path.join(root, d))

I'm sure what I'm doing is very obvious, but it is not obvious to me, so any help will be appreciated.

Thanks!

EDIT: Based on Ben's answer below, here is the code that worked for me:

import os
import shutil

root_dir = r'[path to directory]' # Directory to scan/delete

keep = 'keep' # name of file in directory to not be deleted

for root, dirs, files in os.walk(root_dir):
    for name in files:
        # make sure what you want to keep isn't in the full filename
        if (keep not in root and keep not in name):
            os.unlink(os.path.join(root, name)) # Deletes files not in 'keep' folder
    for name in dirs:
        if (keep not in root and keep not in name):
            shutil.rmtree(os.path.join(root, name)) # Deletes directories not in 'keep' folder
Community
  • 1
  • 1
redjax
  • 63
  • 1
  • 6

3 Answers3

3

Modified Version: It may help if you are using Windows OS

import os
import shutil

root_dir = r'C:\Users\Venus\scarap'

for root, dirs, files in os.walk(root_dir):

    for name in files:
            print(os.path.join(root, name)) 
            os.remove(os.path.join(root, name))
    for name in dirs:
            print(os.path.join(root, name))
            shutil.rmtree(os.path.join(root, name))
Blaztix
  • 1,223
  • 1
  • 19
  • 28
3

a quick and dirty approach:

  • use shutil.rmtree to destroy the directory and its contents
  • re-create the top directory

it may create the new top directory with other permissions, though, or may fail if the directory is write protected, but in most cases it will be ok.

import shutil,os

root = r"C:\path\to\root"
shutil.rmtree(root)
os.mkdir(root)
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
1

I would not check equality, but whether your path contains the folder you want to keep. This example is adapted from the docs (scroll up a little to see it)

import os

# change this, obviously
root_dir = r'C:\Users\ben\Documents\Python Scripts\tmp'

keep = 'keep'

for root, dirs, files in os.walk(root_dir):
    for name in files:
        # make sure what you want to keep isn't in the full filename
        if (keep not in root and keep not in name):
            print(os.path.join(root, name)) #change to os.remove once sure
    for name in dirs:
        if (keep not in root and keep not in name):
            print(os.path.join(root, name)) # change to os.rmdir once sure

Note: depending on how detailed your keep is, this might not erase some files you want to erase: rm_me\keep.txt will be kept even though it's not in the right directory. Detailed folder names can help with this: if keep is something like r'C:\very_specific', that won't be the name of a file, and you'll erase everything you need.

Ben
  • 5,952
  • 4
  • 33
  • 44