1

I want to do the following. I have depth 2 file hierarchy like this:

A
| B
| | g
| | h50000
| C

Where A, B, C are folders. I want to delete all folders without files matching specific patters, (in my case 50000 is pattern, glob style) on depth level 2. (In this example folder C should only be deleted, alongside its content, while A remains)

In my application I'm fine if I delete all folders where neither children contains filename matching a pattern. (It would make it easier to not delete A without specifying on which depth I'm deleting).

How would I be able to do it in bash on Linux machine?

1 Answer 1

1

With find you could exclude a pattern:

find \! -name '*50000*' -delete

Escaping ! is necessary due to its usage in shells.

Directories with contents will not be deleted.

WARNING: since from your question it is a bit unclear to me - this WILL delete other files in folders that have a 50000 pattern, e.g. A/B/g will be removed and only files (and dirs) with name 50000 (including their parent direcories) be kept!


For deleting all directories that have no 50000 file in them and keep directories with such files along with the other contents of this directory, I'd suggest a two-step method:

  1. list all files and directories and safe into text file

    find . -depth -mindepth 1 > all
    
  2. list directories that need to be kept (find file and print dir only)

    find . -depth -name '*50000*' printf '%h\n' > keep
    
  3. pick the deletable files and directories with an inverted grep

    grep -vf keep all > deletable
    
  4. use this list for deletion (just a sample)

    while read line 
    do
    
       find . -wholename "$line" -delete
    
    done < deletable
    

Note that point 4 is slow due to the nature of being a line-per-line shell script. Not the nicest, but will do the job.


Alternatively (and simpler): If you have root access intermedially change the i-attribute, preventing changes, including deletion, delete everything (as deletion is not allowed for i-flagged files and dirs), and remove the i flag in the end.

#%h goes for parent directories of our hits
find -name '*5000*' -printf '%h\0' | xargs -0 chattr -R +i '{}'
#be careful now ....
rm -r *
chattr -i -R *

You must log in to answer this question.

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