harris9050
harris9050

Reputation: 21

How to use Bash to delete unwanted files/folders

I'm trying to utilize a bash script to delete some unwanted files with the same name in different directories, eg: text1.txt exists in multiple directories and I wish to remove it in every directory it exists in.

I need the script to delete the unwanted files and then also delete the directory in which that filename 'text1.txt' exists, so if it exists in a folder named 'TextFiles' I need that folder directory to be deleted.

This is my current code I'm working on:

for files in "/*"
do 
rm file.1txt file2.txt file3.txt

I'm a bit curious about whether the "/*" will look into all directories and whether the 'do' is working to remove the files stated.

Also, after utilising the 'rm' to remove specific files how do I delete the directory it exists in.

Many thanks!

Upvotes: 1

Views: 4207

Answers (2)

Raman Sailopal
Raman Sailopal

Reputation: 12917

You know the extension of the file name and so you can utilise this in a loop parsing the output of find with parameter expansion and so:

find /path -name "file1.txt" | while read var
do 
     echo "rm -Rf ${var%/file1.txt}" # echo the command
     # rm -Rf "${var%/file1.txt}" # execute the command when sure that command list as expected
done 

${var%/file1.txt} -

will expand the output from find and expand the output only up to /file1.txt (the directory) rm -Rf will then force removal the directory along with the file

Alternatively you can use printf natively in find to print only the directory without the file:

find /path -name "file1.txt" -printf "%h\n" | while read var
do 
     echo "rm -Rf $var" # echo the command
     # rm -Rf "$var" # execute the command when sure that command list as expected
done 

Upvotes: 3

Imre Kneifel
Imre Kneifel

Reputation: 56

Before I start, I have to note that the rm command can do some nasty things in your system. Automating it can lead to unintended data loss (system or personal files and folders) if used carelessly.

Now that I said that, imagine the following file structure:

bhuiknei@debian:~/try$ tree
.
├── dir1
│   └── this.txt
└── dir2
    ├── dir3
    │   ├── this
    │   └── this.txt
    ├── notthis.txt
    └── this.txt

3 directories, 5 files

To find and filter specific files find and grep are your friends. The "-w" option will match to whole words only (so the notthis.txt is not picked up):

bhuiknei@debian:~/try$ find . | grep -w this.txt
./dir1/this.txt
./dir2/dir3/this.txt
./dir2/this.txt

Now that we have all paths for the files lined up, these can be piped into a while loop where we can delete the files one-by-one. Then the empty directories can be deleted in a second step.

I would not suggest deleting the containing folders forcibly as they might contain other files and folders too.

The following script does the trick:

#!/bin/bash

#Exiting if no file name was given
[[ $# -ne 1 ]] && { echo "Specify a filename to delete in all sub folders"; exit 1; }

#Deleting files matching input parameter
echo "Deleting all files named ${1} in current and sub-directories."
find . | grep -w "$1" | \
    while IFS= read LINE; do
        rm -v "$LINE"
    done

#Deleting only-empty folders
rmdir -v *

exit 0

And the result:

bhuiknei@debian:~/try$ tree
.
├── dir1
│   └── this.txt
├── dir2
│   ├── dir3
│   │   ├── this
│   │   └── this.txt
│   ├── notthis.txt
│   └── this.txt
└── script

3 directories, 6 files
bhuiknei@debian:~/try$ ./script this.txt
Deleting all files named this.txt in current and sub-directories.
removed './dir1/this.txt'
removed './dir2/dir3/this.txt'
removed './dir2/this.txt'
rmdir: removing directory, 'dir1'
rmdir: removing directory, 'dir2'
rmdir: failed to remove 'dir2': Directory not empty
rmdir: removing directory, 'script'
rmdir: failed to remove 'script': Not a directory
bhuiknei@debian:~/try$ tree
.
├── dir2
│   ├── dir3
│   │   └── this
│   └── notthis.txt
└── script

2 directories, 3 files

Also a side note: I didn't test what happens if the working directory is different where the script is located, so make sure to run it locally from the parent dir, or add some protection. Working with absolute paths can be a solution.

Good luck!

Upvotes: 3

Related Questions