How to recursively delete multiple files with different extensions? - linux

I am trying to write a command to remove recursively several files with different extensions (*.extension1, *.extension2 etc) from the current directory and all its related sub-directories.
So far I got this command from another post but I couldn't workout how to adapt it to more than one file in the same command line:
find . -name "*.extension1" -type f -delete
Is it as simple as below?
find . -name "*.extension1";"*.extension2" -type f -delete
Just as a side note, these are all output files that I do not need, but not all are necessarily always output so some of the extensions might not be present. This is just as a general clean-up command.

find . \( -name "*.extension1" -o -name "*.extension2" \) -type f -delete
find Documents ( -name ".py" -o -name ".html" ) -exec file {} \;
OR
find . -regextype posix-egrep -regex ".*\.(extension1|extension2)$" -type f -delete

Just add more options. A regex solution can also apply but this one's better and safer.
find . \( -name '*.ext1' -or -name '*.ext2' \) -type f -delete
Edit: You probably need -or as well. Before deleting, test it first without the -delete option. (2) Added a pair of () as suggested by gniourf_gniourf.

Maybe regexp will help you
find . -regextype posix-awk -regex "(.*.ext1|.*.ext2)" -type f -delete

Another solution using rm:
rm -rf ./**/*.{txt,nfo,jpg,jpeg,png,exe,url}
If you want to delete other files too for e.g. those starting with sample. just add that too:
rm -rf ./**/*.{txt,nfo,jpg,jpeg,png,exe,url} ./**/*/sample.*

This simple command will delete all the files with extension1 and extension2 recursively in that directory.
rm find . -name *.extension1 -o -name *.extentions2

Related

Remove files in subdirectories older than 1 day with Linux command

I am honestly nowhere near to be a decent bash scripter, but I made a little research and found a command that seems to be useful
find /path/to/files* -mtime +1 -exec rm {} \;
The question is if this line will remove directories? Because I want to only remove files that are images (actually in a *.jpeg format)
No, rm without the -r flag does not remove directories.
It looks like you want to add some more filters:
-type f to match only files
-name '*.jpeg' to match only files ending with .jpeg
Lastly, instead of -exec rm {} \;, you could use the much simpler -delete.
Putting it together, this looks more appropriate for you:
find /path/to/files* -mtime +1 -type f -name '*.jpeg' -delete
Then narrow your search results to *.jpeg files:
find /path/to/files* -mtime +1 -type f -name "*.jpeg" -exec rm {} \;
It's always better to remove the exec parameter to do a dry run before delete:
find /path/to/files* -mtime +1 -type f -name "*.jpeg"
Each line will be passed to rm command, and nothing more.

Using "find … -delete" to remove image files only from special subdirectories

I need to clean up some subdirectories inside my music collection from unwanted images. I’m using Ubuntu 14.04 and/or Linux Mint 17.2 and a bash shell script using the find command.
The directory structure (minimal example) is as follows:
Tagged
Artist #1
Artist #1 - An Album
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #1 - [compilations]
Artist #1 - A Track.flac
cover.jpg
something.png
Artist #2
Artist #2 - Another Album
Artist #2 - A Track.mp3
cover.jpg
Only in the subfolders ending with "[compilations]", I want to delete all kind of jpeg and/or png images (because the tagging software erroneously puts them there). Any images that happen to be in normal "album" folders I wish too keep.
With my directory structure, folders with "[compilations]" in the name can only happen just below the "Artist" folders, repectively; so a maximum of two levels deep.
I came up with the following find command:
$ cd Tagged
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' -delete \;
This seems to do something and takes a while, but the files "./Artist #1/Artist #1 - [compilations]/cover.jpg" and "./Artist #1/Artist #1 - [compilations]/something.png" are still there (and all other image files).
Being quite new to Linux, I assume I make a dumb mistake using find's -delete option, because the following command (without -delete) shows the files correctly:
$ find . -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f -iname '*.jp*g' -or -iname '*.png' \;
./Artist #1/Artist #1 - [compilations]/cover.jpg
./Artist #1/Artist #1 - [compilations]/something.png
So here are my questions:
Why does the -delete not work?
Is this command really safe regarding "extravaganza" like whitespace, glob characters and foreign characters in the paths and filenames?
How would I have to rewrite the above command, still using bash and find?
Could the command be optimized (re speed, safety, nested finds)?
In the actual collection, the command must traverse 16899 folders, almost all of them contain whitespace and foreign characters (like Czech, Russian, Japanese, Greek, German …), so it must be robust.
Thanks in advance for any insights and some enlightenment!
Your -delete predicate only applies to the
-iname '*.png'
predicate, because you missed groupings: when you give find the following:
-type f -iname '*.jp*g' -or -iname '*.png' -delete
because of the precedence of the boolean operators, find understands:
\( -type f -iname '*.jp*g' \) -or \( -iname '*.png' -delete \)
To fix this, use:
-type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete
I'd suggest that to experiment you replace -delete with -print: you'll see what the -delete applies to!
Now, regarding your nested find: because of the structure of your directory tree (your files are only in depth 3), you should be able to do with only one instance of find:
find -maxdepth 3 -path '*/*\[compilations\]/*' \( -iname '*.jp*g' -o -iname '*.png' \) -type f -print
(I put -print instead of -delete so that you can check the command before executing it with -delete).
After some experimentation, I think my error was in not putting the OR'ed part in parentheses—it seems find used the -delete only on the right part of the last OR, i.e., tried to delete '*.png'. Alas, almost all of my cover images were '*.jpg' so I thought it wouldn't work at all!
So I think the corrected command should be:
$ find . -depth -maxdepth 2 -type d -name '*\[compilations\]' -exec find {} -type f \( -iname '*.jp*g' -or -iname '*.png' \) -delete \;
It seems to work correctly on my test case above.
Nevertheless, some confirmation would be nice. An maybe some answers to my other questions, just for information and learning. Thank you!

Bash: numbered files in Find

I was writing a bash script that finds and deletes the .blend1 and .blend2 files that blender creates as you edit and save .blend files. It contains lines in pairs like this:
find Documents -name "*.blend1" -exec rm -rf {} \;
find Documents -name "*.blend2" -exec rm -rf {} \;
This works just fine, though I was curious if it is at all possible to combine those two find commands some way, so that it would be just one command that finds and deletes both .blend1 and .blend2 files.
Not super-important, I'd just prefer it if my script were a little more compact.
find Documents -name '*.blend[12]' -delete
(-delete is a GNU find extension.)
Other ways:
find Documents '(' -name '*.blend1' -o -name '*.blend2' ')' -delete
find Documents -name '*.blend*' -delete
Here's another way...
find Documents -name '*.blend[12]' -exec rm -rf {} \;
Yes you can use regex to match more that one patterns into one:
find Documents -regextype posix-egrep -regex '.*\.(blend1|blend2)$' -exec rm -rf {} \;
Or with newer find versions:
find Documents -regextype posix-egrep -regex '.*\.(blend1|blend2)$' -delete
Without regex you can do:
find Documents \( -name "*.blend1" -o -name "*.blend2" \) -delete

excluding a directory from find and sed rename

I'm using this command to go through all files, directories and subdirectories to change any mentions of oldurl.com to newurl.org:
find . -type f -name '*.php' -exec sed -i 's|oldurl.com|newurl.org|g' {} +
It works fine, however, I need to exclude three sub-directories from ANY CHANGES: /cache, /archive and /etc as changing the urls with the above command in these paths breaks other scripts.
Haven't had much luck finding an answer... Is it even possible?
Many thanks for any suggestions/help.
Use finds -not Option:
find . -type f -name '*.php' -not \( -path './etc/*' -o -path './cache/*' -o -path './archive/*' \) -exec sed -i 's|oldurl.com|newurl.org|g' {} \;

How to find all files with a filename that ends with tilde

I use Emacs and it sometimes makes backup for edited files. After a few days, I would have a lot of backup files whose name ends with a tilde.
Is there a way to find these files and delete them at once?
I tried this:
find "*" -type f -iname *~
But it doesn't work. I want the command to work recursively – something like ls -alR.
You need to escape from the shell. And you need to specify search path, not *
find . -type f -name '*~'
To delete the files:
find . -type f -name '*~' -exec rm -f '{}' \;
You can do something like that :
find . -type f -name '*~' -delete
If you want to delete also #*# file :
find . -type f -name '*~' -o -name '#*#' -delete
You can print all deleted files with "-print":
find . -type f -name '*~' -delete -print
Another way is by using grep.
lnydex99uhc:javastuff user$ ls
Permutation.java VigenereCipher.java VigenereCipher.java~
lnydex99uhc:javastuff user $ find . | grep .~$
./VigenereCipher.java~
You can also pass any command you want like this :
lnydex99uhc:javastuff zatef$ rm $(find . | grep .~$)

Resources