How can I recursively delete a set of directories across a large array of different folders using bash? - linux

I have several config folders (ex: .gnome, .mozilla) that I need to delete across a large array of directories. They all start with two alphabetical characters (ex: ag52156,ge51789) and are located in the same place.
I don't write bash so I wouldn't know how to start tackling this in the first place - but what should I look into so that I can write this?

Try this :
find [a-z][a-z]* -type d \( -name .gnome -o -name .mozilla \) -exec rm -r {} \;

Related

How can I remove specific directories that all start with a common letter?

I have many EC2 instances in a folder that I need to delete. Using -delete doesn't work because the directories are not empty. I tried looking for a way to get -rmdir -f to work with no success. The instance folders are all started with "i-" which led me to add wildcard "i-*" like that to get it to delete all directories starting with those characters. How can I manage to do this? the directories will never be empty either.
Assuming your current dir is the folder in question, how about:
find . -type d -name 'i-*'
If that lists the directories you want to remove, then change it to:
find . -type d -name 'i-*' -exec rm -r {} \;
In the command line interface/shell/born again shell/etc...
rm -r i-*
will remove ANY and ALL contained file(s) or directory(s) with subfiles and sub directories (recursive = -r) where the name begins with "i-" .
To delete the directories matching the pattern graphene-80* directly under /tmp, use
rm -rf /tmp/graphene-80*/
Here, the trailing / ensures that only directories whose names match the graphene-80* pattern are deleted (or symbolic links to directories), and not files etc.
To find the matching directories elsewhere under /tmp and delete them wherever they may be, use
find /tmp -type d -name 'graphene-80*' -prune -exec rm -rf {} +
To additionally see the names of the directories as they are deleted, insert -print before -exec.
The two tests -type d and -name 'graphene-80*' tests for directories with the names that we're looking for. The -prune removes the found directory from the search path (we don't want to look inside these directories as they are being deleted), and the -exec, finally, does the actual removal by means of calling rm.

Find numbered subdirectories below number X and delete them

I have a folder 'masterfolder' that has subfolders with a numbered naming scheme:
\masterfolder\S01
\masterfolder\S02
\masterfolder\S03
\masterfolder\S04
\masterfolder\S05
Now I want to find and delete all folders below a specific number, for example S03. This means, S03, S04, S05 etc should not get deleted, S01 and S02 should get deleted.
I normally use this command to find and delete a specific folder:
find "/mnt/USBDRIVE/masterfolder" -type d -name "S02" -exec rm -rf '{}' \;
I tried finding a solution myself, but the only method I have found is to delete everything except the number I know I want to keep:
find "/mnt/USBDRIVE/masterfolder" -mindepth 1 -maxdepth 1 -type d -not -name "S03" -exec rm -rf '{}' \;
This will keep S03, but delete all others. I want to keep S03 and any other folder with a higher number than S03.
Any ideas appreciated.
There are many ways to solve this.
Since your numbers are zero padded, the easiest way is to just send a list of the directories to a file sorted alphabetically. Then delete the ones you want ignored (they'll all be together), do a global change to add "rm " to the beginning of each line, and run the file as a script.
This will take you less than 30 seconds. Any programmatic solution will take longer.

Get list of files that contain given text within directory given by pattern

I want to get a list of files that contain a given text within my file-system. Furthermore only files should be considdered that are located in a directoy given by a pattern.
So let´s say I have a number of directories called myDir within my filelsystem as shown here:
/usr
/myDir
/tmp
/myDir
/anotherDir
Now I want to get all the files within those directories that contain the text.
So basically I need to perform these steps:
loop all directories names myDir on the whole file-system
for every directory within that list get the files that contain the search-string
What I tried so far is find /etc /opt /tmp /usr /var -iname myDir -type d -exec ls -exec grep -l "SearchString" {} \;
However this doesn´t work as the results of find are directories which I may not use as input for grep. I assume I have to do one step in between the find and the grep but can´t find out how to do this.
I think I got it and will show you a little script that achieves what I need:
for i in $(find / -type d -iname myDir) do
for j in $(find "$i" -type f) do
grep "SearchString" "$j"
done
done
This will give me all the files that contain the SearchString and are located in any of the folders named myDir.

how to exclude all subdirectories of a given directory in the search path of the find command in unix

I need to backup all the directory hierarchy of our servers, thus I need to list all the sub directories of some of the directories in the server.
The problem is that one of those sub directories contains tens of thousands of sub directories (file with only the names of the sub directories could take couple of hundreds megabytes and the respective find command takes very long).
For example, if I have a directory A and one sub directory A/a that contains tens of thousands of sub directories, I want to use the find command to list all the sub directories of A excluding all the sub directories of A/a but not excluding A/a itself.
I tried many variations of -prune using the answers in this question to no avail.
Is there a way to use the find command in UNIX to do this?
UPDATE:
the answer by #devnull worked very well, but now i have another problem, so i will refine my question a little:
i used the following command:
find /var/www -type d \( ! -wholename "/var/www/web-release-data/*" ! -wholename "/var/www/web-development-data/*" \)
the new problem that arises is that find for some reason is still traversing the whole directory tree of "/var/www/web-release-data/" and "/var/www/web-development-data/", thus it's very slow, and I fear it could take hours.
Is there any way make find completely exclude those directories and not traverse their respective directory hierarchies?
The following should work for you:
find A -type d \( ! -wholename "A/a/*" \)
This would list all subdirectories of A including A/a but excluding subdirectories of A/a.
Example:
$ mkdir -p A/{a..c}/{1..4}
$ find A -type d \( ! -wholename "A/a/*" \)
A
A/c
A/c/4
A/c/2
A/c/3
A/c/1
A/a
A/b
A/b/4
A/b/2
A/b/3
A/b/1
Another solution:
find A \! -path "A/a/*"
If you don't want a as well, use
find A \! -path "A/a/*" -a \! -path "A/a"
Have you tried rsync(1)? It has an option --exclude=PATTERN which might work well here:
rsync -avz --exclude=A/a <source> <target>
Using rsync you wouldn't need to use find(1)
To exclude 2 subdirs:
find . -type d ! -wholename "dir/name/*" -a ! -wholename "dir/name*"
To answer your updated question, you can do
find /var/www -wholename "/var/www/web-release-data/*" -o -wholename "/var/www/web-development-data/*" -prune -o -type d -print

Merging Sub-Folders together, Linux

I have a main folder "Abc" which has about 800 sub-folders. Each of these sub-folders contains numerous files (all of the same format, say ".doc"). How do I create one master folder with all these files (and not being distributed into subfolders). I am doing this on a Windows 7 machine, using cygwin terminal.
The cp -r command copies it but leaves the files in the sub-folders, so it doesn't really help much. I'd appreciate assistance with this. Thank you!
Assuming there could be name collisions and multiple extensions, this will create unique names, changing directory paths to dashes (e.g. a/b/c.doc would become a-b-c.doc). Run this from within the folder you want to collapse:
# if globstar is not enabled, you'll need it.
shopt -s globstar
for file in */**; do [ -f "$file" ] && mv -i "$file" "${file//\//-}"; done
# get rid of the now-empty subdirectories.
find . -type d -empty -delete
If you can guarantee unique names, this will move the files and remove the subdirectories. You can change the two .s to the name of a folder and run it from outside said folder:
find . -depth \( -type f -exec mv -i {} . \; \) -o \( -type d -empty -delete \)
This may not be the most elegant or efficient way to do it, but I believe it'd accomplish what you want:
for file in `find abc`
do
if [ -f $file ]
then
mv $file `basename $file`
fi
done
Iterate through everything in abc, check if it's a file (not a directory) and if it is then move it from its current location (eg abc/d/example.txt) to abc/
Edit: This would leave all the subfolders in place (but they'd be empty now)

Resources