Recursively delete files named `log` under multiple directories - linux

I have a folder structure like the below:
feat1
feat2
feat3
Now within each folder we have another folder called builds.
Under builds we have numbered folders like 1, 2, etc.
Under each numbered folder we have files of the pattern *.log and then a particular file with the name log.
I need to run a command in the linux server / unix server to recursively delete only the file with the name log not the *.log for all these folders feat1, feat2 and feat3. How to do that?

The command you run depends on how careful you want to be about your search criteria and whether you need to search recursively.
Delete anything named log under feat*/builds/*/:
rm feat*/builds/*/log
Recursively find and delete anything named log anywhere under the current directory:
find . -name log -delete
Recursively find and delete anything named log, only under feat*:
find feat* -name log -delete
Recursively find and delete anything named log, only under feat*/builds/*/:
find feat*/builds/*/ -name log -delete
Recursively find and delete any file named log, only under feat*/builds/*/:
find feat*/builds/*/ -name log -type f -delete

Here is a quick and dirty solution using a for loop that should get the job done.
for f in `find feat* -name 'log'`; do rm "$f"; done;
for f in is saying we're going to do a for loop with f as the variable for each result.
find feat* -name 'log' searches through any directory starting with "feat" with * as a wildcard.
-name says we're looking for a file name of log.
do rm "$f" removes each result that was found.
Sometimes it is helpful to use echo before doing destructive commands this way. See below.
for f in `find feat* -name 'log'`; do echo "$f"; done;

Related

Find all files with specific name and move it two levels up from its location

I want to find all files with specific name "stdout.1.0", move it two/three levels up from its location. While moving it two/three levels up, I also want to rename it to "testjob.out".
All "stdout.1.0" files are located six levels down from parent directory.
./dirXXXXXX/dirXXXXXX/dirXXXXXX/dirXXXXXX/dirXXXXXX/dirXXXXXX/stdout.1.0
I used:
find . -type f -name stdout.1.0
and it outputs:
./dir100000/dir110000/dir111000/dir111100/dir111110/dir111111/stdout.1.0
./dir100000/dir110000/dir112000/dir111100/dir111110/dir111111/stdout.1.0
./dir100000/dir110000/dir113000/dir111100/dir111110/dir111111/stdout.1.0
./dir200000/dir210000/dir211000/dir211100/dir211110/dir211111/stdout.1.0
./dir200000/dir210000/dir212000/dir211100/dir211110/dir211111/stdout.1.0
./dir200000/dir210000/dir213000/dir211100/dir211110/dir211111/stdout.1.0
./dir300000/dir310000/dir311000/dir311100/dir311110/dir311111/stdout.1.0
./dir300000/dir310000/dir312000/dir311100/dir311110/dir311111/stdout.1.0
./dir300000/dir310000/dir313000/dir311100/dir311110/dir311111/stdout.1.0
.
.
./dirXXX000/dirXXX000/dirXXX000/dirXXX100/dirXXX110/dirXXX111/stdout.1.0
The directories above is just representative of where the file is, but there are multiple "stdout.1.0" files starting three levels down from parent directory.
Here is a method in plain bash using globstar shell option , without using the find:
#!/bin/bash
shopt -s globstar
for file in **/stdout.1.0; do
echo mv "$file" "${file%/*/*/*}/testjob.out"
done
Drop the echo if output looks fine.
You already know how to find them:
find . -type f -name stdout.1.0
Now, you need to move them to a higher directory (..) and rename them:
find . -type f -name stdout.1.0 -execdir mv {} ../../testjob.out \;
I would advise you to copy them first and remove later (use cp instead of mv): if anything goes wrong, you can get back easily to the current situation.

How to remove all files except the ones that matches a pattern along several number of directories

lets say I have a my_dirs/ directory, insdie that directory I have several parallel subdirectories which has several files and I want to delete all of them except the ones that have the substring '.regions'
this is my parent directory content:
this is what I tried:
shopt -s extglob
rm -r !(./**/*.regions*)
but I got an error message: cannot be deleted «! (./**/*. region *) »: The file or directory does not exist.
how can I do that?
First of all, always be careful when deleting multiple files.
The command to achieve what you want would be:
find my_dirs -type f ! -name "*.regions*" -delete
"-delete" must be last, otherwise it will delete everything it finds
This will explore all subdirectories in my_dirs, find the files (-type f) that not (!) contain ".regions" ("*.regions*") on their name, and delete (-delete) them.
I recommend running this first: find my_dirs -type f ! -name "*.regions*",
so it won't delete anything and you can check the files are correct.
Edit: Added -type f so it only targets files per Philippe's suggestion.

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.

Remove files for a lot of directories - Linux

How can I remove all .txt files present in several directories
Dir1 >
Dir11/123.txt
Dir12/456.txt
Dir13/test.txt
Dir14/manifest.txt
In my example I want to run the remove command from Dir1.
I know the linux command rm, but i don't know how can I make this works to my case.
PS.: I'm using ubuntu.
To do what you want recursively, find is the most used tool in this case. Combined with the -delete switch, you can do it with a single command (no need to use -exec (and forks) in find like other answers in this thread) :
find Dir1 -type f -name "*.txt" -delete
if you use bash4, you can do too :
( shopt -s globstar; rm Dir1/**/*.txt )
We're not going to enter sub directories so no need to use find; everything is at the same level. I think this is what you're looking for: rm */*.txt
Before you run this you can try echo */*.txt to see if the correct files are going to be removed.
Using find would be useful if you want to search subfolders of subfolders, etc.
There is no Dir1 in the current folder so don't do find Dir1 .... If you run the find from the prompt above this will work:
find . -type f -name "*.txt" -delete

bash on Linux, delete files with certain file extension

I want to delete all files with a specific extension - ".fal", in a folder and its subfolders, except the one named "*Original.fal". The problem is that I want to delete other files that have the same extension:
*Original.fal.ds
*Original.fal.ds.erg
*Original.fal.ds.erg.neu
There are other ".fal"s that I want to delete as well, that don't have "Original" in them.
Names vary all the time, so I can't delete specific names. The *Original.fal doesn't vary.
I can only get up to here:
$find /disk_2/people/z183464/DOE-Wellen -name "*.fal" \! -name "*Original.fal" -type f -exec echo rm {} \;
It would be great if the command can delete only in the folder (and it's subfolders) where it has been called (executed)
When I run the code it gives me an error:
/disk_2/people/z183464/DOE-Wellen: is a directory
If you do not want find to dive too deep, you can restrict it with -maxdepth.
You can use a simple for loop for that. This command shows all the files you might want to delete. Change echo with rm to delete them.
cd /disk_2/people/z183464/DOE-Wellen && for I in `find . -name "*.fal" ! -name "*Original.fal"`; do echo $I; done
With "find ... | grep ..." you can use regex too, if you need more flexibility.

Resources