DylanDog
DylanDog

Reputation: 109

BASH Script - Delete folders older than X days except for some and all their subfolders/files

I'm actually testing this script

find /Path/Folder/* -type d -mtime +7 ! -path "/Path/Folder/NODELETE1/*"  ! -path "/Path/Folder/NODELETE2/*"  ! -path "/Path/Folder/NODELETE3/*" -exec rm -rf {} \;

to delete all files/folders older than 7 days except for NODELETE1, NODELETE2 and NODELETE3 folders.

The issue is that it apparently doesn't work, because of it deletes these folders and all files inside.

This is what I want to do:

I have

/Path/Folder/NODELETE1/some files and folders
/Path/Folder/NODELETE2/some files and folders
/Path/Folder/NODELETE3/some files and folders
/Path/Folder/AFOLDER/somefiles and folders
/Path/Folder/ANOTHERFOLDER/somefiles and folders
/Path/Folder/...
/Path/Folder/FILE
/Path/Folder/ANOTHERFILE
/Path/Folder/...

I want to delete automatically all files and folders older that 7 days (so FOLDER, ANOTHERFOLDER, ..., FILE, ANOTHERFILE, ...) so that

/Path/Folder/NODELETE1/some files and folders
/Path/Folder/NODELETE2/some files and folders
/Path/Folder/NODELETE3/some files and folders

What's wrong with the script?

EDIT with the script suggestion:

#!/bin/bash

while IFS= read -r -d '' dir
do

    # This line actually halts the control from entering if 
    # dirname contains either of the three names below. You could
    # remove it and put your actual folder names.

    [[ $dir =~ ^(NODELETE1|NODELETE2|NODELETE3)$ ]] && continue

    # Suggest un-commenting the echo line below and comment rm to ensure
    # you have only the folders you want to delete. 
    echo "$dir"

    # rm -rf "$dir"     
done< <(find /Users/Username/Desktop/test/* -type d -mtime +7 -print0)

For testing, I have:

/Users/Username/Desktop/test/NODELETE1
/Users/Username/Desktop/test/NODELETE2
/Users/Username/Desktop/test/NODELETE3
/Users/Username/Desktop/test/YESDELETE

and the script path

/Users/Username/Desktop/TEST.sh

Upvotes: 2

Views: 2234

Answers (3)

Eilyre
Eilyre

Reputation: 466

TL;DR Fix:

Instead of your line, do:

find /Path/Folder/* -type d -mtime +7 ! -path "/Path/Folder/NODELETE1"  ! -path "/Path/Folder/NODELETE2"  ! -path "/Path/Folder/NODELETE3" -exec rm -rf {} \;

Longer explanation:

The -type d part of your line searches for Directories only. But what you're excluding, are things inside your NODELETE directories. This still means that your NODELETE directories are targets for rm -rf and due to that they get recursively deleted.

Upvotes: 2

Inian
Inian

Reputation: 85550

Instead of relying on the core utils of the find command, I would suggest let bash take care of it ( you have tagged bash anyway) to exclude folders having the specific names,

#!/bin/bash

while IFS= read -r -d '' dir
do

    # This line actually halts the control from entering if 
    # dirname contains either of the three names below. You could
    # remove it and put your actual folder names.

    [[ $dir =~ ^(NODELETE1|NODELETE2|NODELETE3)$ ]] && continue

    # Suggest un-commenting the echo line below and comment rm to ensure
    # you have only the folders you want to delete. 
    # echo "$dir"

    rm -rf "$dir"     
done< <(find /Path/Folder/* -type d -mtime +7 -print0)

Upvotes: 2

Stev tuned
Stev tuned

Reputation: 65

Escape the ! as

 \! -path

to be sure it will not interpreted as pattern

Upvotes: 1

Related Questions