How do I safely delete all files with a specific extension (e.g. .bak) from current directory and all subfolders using one command-line? Simply, I'm afraid to use rm since I used it wrong once and now I need advice.
- 21,393
- 9,013
-
Related post - How do I recursively delete directories with wildcard? – RBT Dec 06 '19 at 09:37
9 Answers
You don't even need to use rm in this case if you are afraid. Use find:
find . -name "*.bak" -type f -delete
But use it with precaution. Run first:
find . -name "*.bak" -type f
to see exactly which files you will remove.
Also, make sure that -delete is the last argument in your command. If you put it before the -name *.bak argument, it will delete everything.
See man find and man rm for more info and see also this related question on SE:
- 169,590
-
1
-
24
-
With default settings
rm *.bakwill only delete all files ending with .bak in the current directory. TO also do things in subdirectories you either needed to fiddle with globs, use the -r option or use the find example. – Hennes Nov 15 '13 at 13:14 -
-
You might want to add a '-print
to the second example. If you do not specify this then printing is the default, but explicitly stating it is a good idea in case you ever move to an OS which has different defaults. (Same with the.which was mentioned. If you leave that out then some find binaries will assume.` and some will complain about invalid syntax. – Hennes Nov 15 '13 at 13:17 -
16@Hennes Be careful with
rm -r *.bak! It also removes directories ending in.bakwith all their content. – Radu Rădeanu Nov 15 '13 at 13:34 -
True. Without the -r it prints a nice warning. (at least on FreeBSD with bash where I tested it). And maybe we should mention rm's
-iflag since it will answer the key problem of the OP: "Not feeling safe with rm". – Hennes Nov 15 '13 at 13:35 -
More generally, you can use e.g.
find . -name "*.bak" -type f -print0 | xargs -0 gvfs-trash. (The-print0and the-0switch to xargs are important if your filenames might contain spaces or newlines.) Again, it's a good idea to first run justfind . -name "*.bak" -type fso you can see what's going to be trashed. – Ilmari Karonen Nov 15 '13 at 21:04 -
@RaduRădeanu,
rm -r *.bakwould delete directories suffixed by.bakonly if these directories are empty, correct ? – Muhammad Gelbana Nov 23 '13 at 20:21 -
-
@RaduRădeanu How can I do the same for two different types of files (for example
*.png&*.jpg) without running the command twice? – Khurshid Alam Jun 30 '14 at 13:37 -
@KhurshidAlam
find . -name "*.png" -or -name "*.jpg" -type forfind -regex ".*\.\(png\|txt\)" -type f– Radu Rădeanu Jul 01 '14 at 19:52 -
@MohammedArif If you didn't observed yet, you are on askubuntu.com, not on askwin7.com :) – Radu Rădeanu Aug 21 '14 at 08:27
-
-
65Make sure that
-deleteis the last argument in your command. If you put it before the-name *.bakargument, it will delete everything. – Michael come lately Oct 29 '14 at 14:36 -
Thanks @RaduRădeanu. In my opinion, for passing many wildcards, it is cumbersome to do
-or -name *.xyzfor the many different patterns. On windows, it is simply:del /S *.txt *.log *.tmp *.ttx *.dox *.exe– Shailen Dec 30 '15 at 13:35 -
The precautionary advice is the best part :) Dry run to confirm the files before the actual
delete. – SKPS Oct 11 '16 at 12:09 -
You might want to use
-iname "*.bak"for a case-insensitive match, to get rid of.BAKfiles as well. – Márton Tamás May 28 '18 at 17:38 -
@RaduRădeanu Still a great answer after all these years! On my own system I add another safety net in this deletion which is the option
-mtime +90. Perhaps this might be useful in your answer, even as a footnote? – andrew.46 Apr 10 '21 at 06:32 -
-
-
I can't seem to make this work when wanting to delete .volume dirs with `find . -name ".volume" -type d -delete
. Usingfind . -name "*.volume" -type d -print0 | xargs -0 /bin/rm -rd` fixes the problem... is it the dir extension that mangles with the -delete option? – Giuppox Jan 01 '24 at 23:11
First run the command shopt -s globstar. You can run that on the command line, and it'll have effect only in that shell window. You can put it in your .bashrc, and then all newly started shells will pick it up. The effect of that command is to make **/ match files in the current directory and its subdirectories recursively (by default, **/ means the same thing as */: only in the immediate subdirectories). Then:
rm **/*.bak
(or gvfs-trash **/*.bak or what have you).
- 60,593
-
-
Not working in WSL with git bash. Says "rm: cannot remove '*/.md': No such file or directory " – Marian Klühspies Apr 08 '23 at 09:43
-
@MarianKlühspies That just means there are no matching files. – Gilles 'SO- stop being evil' Apr 08 '23 at 10:18
-
@Gilles'SO-stopbeingevil' but there were matching files in sub directories. I've used
find . -name '*.md' -type f -deleteafterwards and deleted them successfully – Marian Klühspies Apr 08 '23 at 10:50
-
1Welcome to askubuntu! While this is a perfectly valid answer I don't think there's any advantage in using this instead of the
-deleteflag offind. More information can be found in the GNU manuals entry for deleting files with find. – Glutanimate Apr 04 '14 at 20:11 -
2you are probably right, it's just an alternative solution, perhaps more raw ;) – lokers Apr 04 '14 at 22:13
-
18This is not just an alternative but an example how other commands can be combined together with the pipe '|'. +1 – Boris Pavlović Jun 05 '14 at 07:18
-
21This alternative solutions work on other environments that lack -delete (like cygwin) – ciriarte Aug 15 '14 at 04:07
-
3
-
1I'm on a legacy Unix HP UX 10.20 system. I was looking for an answer for this post question and landed here.
I don't have the
-deleteflag for thefindcommand. Instead what I did was just this:find /path/to/dir -name "*.bak" -type f | xargs rmWorked great for my need.
– Diego Tercero Jul 22 '15 at 08:37 -
-
-
This will work easily for directories two with some changes, even for filled ones +1 – phrogg Aug 09 '20 at 10:03
Deleting files is for me not something you should use rm for. Here is an alternative:
sudo apt-get install gvfs # install a tool that allows you to put stuff in the trash
alias "trash"="gvfs-trash" # you can also put this in .bash_aliases or simply use the command without alias
trash *.bak # trash the files (thus moving them to the trash bin)
As Flimm states in the comments:
The package
trash-clidoes the same thing asgvfs-trashwithout the dependency on gvfs.
So:
sudo apt-get install trash-cli
You don't need to make an alias for this, because the trash-cli package provides a command trash, which does what we want.
As Eliah Kagan makes clear in extensive comments, you can also make this recursive using find. In that case you can't use an alias, so the commands below assume you have installed trash-cli. I summarise Eliah's comments:
This command finds and displays all .bak files and symlinks anywhere in the current directory or its subdirectories or below.
find . -name '*.bak' -xtype f
To delete them, append an -exec with the trash command:
find . -name '*.bak' -xtype f -exec trash {} +
-xtype f selects files and symlinks to files, but not folders. To delete .bak folders too, remove that part, and use -execdir, which avoids cannot trash non-existent errors for .bak files inside .bak directories:
find . -name '*.bak' -execdir trash {} +
-
7"Don't use
rmto delete things" is a controversial statement but I have to agree that it's often wiser to use something that will let you undo things. – Oli Nov 15 '13 at 15:12 -
2The package
trash-clidoes the same thing asgvfs-trashwithout the dependency ongvfs. – Flimm Nov 20 '13 at 09:08 -
I have edited it in the answer, next time feel free to do the edit yourself. – don.joey Nov 20 '13 at 10:06
-
@don.joey This answer seems to say
find . -name "*.bak" -type fdisplays whattrash *.bakdeletes. Is that really what you mean? You can move directories to the trash withtrashorgvfs-trash, buttrash *.bakwill only moves files and directories whose names end with.bakand that reside immediately in the current directory. The shell expands*.bak, sotrash *.bakwon't affect.bakfiles in subdirectories not themselves named.bak. – Eliah Kagan Oct 14 '17 at 02:30 -
@EliahKagan good spot. Yes, in this case
ls .*bakwould be better. Or do you have an alternative that makestrashrecursive? – don.joey Oct 14 '17 at 13:23 -
1@don.joey Yes
ls *.bak(which I think you mean) lists whattrash *.baktrashes.find . -name '*.bak' -xtype f -exec trash {} +trashes all.bakfiles anywhere under.. It can't use an alias, so installtrash-clior writegvfs-trashinstead. Here's an example.-xtype fselects files and symlinks to files, but not folders. To delete.bakfolders too, usefind . -name '*.bak' -execdir trash {} +, which avoidscannot trash non existenterrors for.bakfiles inside.bakdirectories. Please feel free to use any of this in your answer. – Eliah Kagan Oct 14 '17 at 19:15 -
@EliahKagan much appreciated! have incorporated them, feel free to edit and make it a community wiki if that helps – don.joey Oct 16 '17 at 19:56
-
Excellent idea having a trash option by command line. For those who do not, having an alias such as in bash/zsh: alias rm='rm -i' (same for mv or maybe even rmdir) is often enough to issue a 'are you really sure you want do delete this?' on the command line before rm destroys anything. – Jeff Clayton Aug 13 '21 at 20:57
If you want to delete all files of a certain type, but only 1 folder "deep" from the current folder:
find . -maxdepth 2 -name "*.log" -type f -delete
-maxdepth 2 because the current directory "." counts as the first folder.
- 179
Quick Answer:
Delete all files with the considered name or postfix recursively:
find . -name '*.pyc' -type f -deleteDelete all directories with the considered name recursively:
find ~ -path '*/__pycache__/*' -delete find ~ -type d -name '__pycache__' -empty -deleteSomewhat less tightly controlled, but in a single line:
find ~ -path '*/__pycache__*' -delete
[NOTE]:
d is directory option and f is file option.
- 3,514
If in case you want to check the list before you delete the files, you can echo it.
find . -name "*.bak" -type f | xargs echo rm -rf
This will list out the search results that are piped to rm command via xargs. Once you are sure about the list you can drop the echo in above command.
find . -name "*.bak" -type f | xargs rm -rf
- 131
-
its a good practice to add
-print0 | xargs -0to handle cornercase filenames, exampletest'sgives youxargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 optionor filenames with newlines will break. – Nov 25 '19 at 07:02
You can list all the files with that extension first before you use rm
For example,
ls *.bak
If you get only the files that you want to delete then you can use the rm
rm *.bak
- 21
Once you are confident that all your files of a particular extension (eg. .bak) has to be deleted, just use:
rm -ir *.bak
It will give you a prompt:
rm: remove regular file 'example.bak'?
Answer the prompt with a y for Yes and n for No
-
1This isn't a correct answer to the question unfortunately. What you are suggesting will only delete
.bakfiles in the current folder and any directories named*.bakwhich is almost certainly not what you want. It won't touch files named*.bakin subdirectories – moo Jan 03 '24 at 09:25 -
My aim is not to delete a file name
*.bakbut to delete all the files with extension.bak. And for that the above command is. And for other file extensions we can just change the.bak– Mudassir Ansari Mar 24 '24 at 17:58