Delete all files (including hidden ones) with just one rm
This will match any regular file or directory, plus hidden ones, excluding '.' and '..':
rm -rf {,.[!.],..?}*
And remember: with great power comes great responsibility
Written by Daniel Pecos Martínez
Related protips
12 Responses
rm -rf *
@offirmo, that does not delete hidden files (i.e .htaccess)
You can't delete . or .. so trying does not matter.
rm -rf * .*@lokiastari Of course it matters! If it's part of an script you have to handle errors, and your command ends with an error:
/tmp/test$ rm -rf * .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'
/tmp/test$ echo $?
1
Whereas my version of rm finishes with a success error code:
/tmp/test$ rm -rf {,.[!.],..?}*
/tmp/test$ echo $?
0If you write that in a script that has to be maintained you should be fired.
Have to disagree. Its two ugly to remember for a simple command line
On the command line:
rm -rf . .*
This is just intuitively obvious (unlike the reg-ex monstrosity you concocted) and the error messages are logical. So are not a problem.
In a script (both are stupid but you can correct for the error message):
(rm -rf . .* || echo "Delete * .* Done") 2> /dev/null
This is still so much more readable than your original code.
Though you would still never do that. If this is a repeatable script that you are tidying up from then you are going to do something is easy to read and maintain:
# Clean up the current directory (which we are in)
# This directory holds some state and thus must be cleaned
# So scour it absolutely clean before use.
function scourDirectory {
dir=`pwd`
local=${dir##*/}
cd ..
rm -rf ${local}
mkdir ${local}
cd ${local}
}
Here verbosity is your friend not a hindrance.
@lokiastari Well, I don't quite understand what you're saying about maintaining an script and being fired or not (are scripts written once and remain intact forever without a minimal maintenance?? lol ). I'm not going to enter into that discussion but try to focus on the actual subject.
Anyway, your latest version works fine, but you are not handling exit codes properly. In fact, you don't seem to care about if the rm could or could not delete anything, it just prints "Done" and you swallow all error messages: that's not handling errors, that's covering them. Good luck with that!
I will stay with my version, a little more complex than using an OR but simpler to handle. At least I could known if the rm did in fact delete something or not. As I said in my initial post with great power comes great responsibility
OK. What I am saying is that you would never write either in a script.
So the only place you use this is on a command line.
Given that. Yours is just way too unreadable for general usage and the error messages mine produce are quite fine (or ignorable). In other-words this is not a tip (or even useful).
@lokiastari I needed this command while creating a deployment script for a webapp to a pristine directory structure, so rsync was not a suitable solution.
That's why I needed to empty a directory path completely before making the deployment.
I find it's quite usefull and fits great in the script, and also great used as an alias in the command line.
What about this one?
find ./ -mindepth 1 -maxdepth 1 -exec rm -rf {} \;
Cheers this is exactly what I wanted, both for bash scripts and command line. I've alias'd it :)
alias rma='rm -rf {,.[!.],..?}*'
Oh my, I'd never alias a "rm rf" even if someone put a pistol to my head.
I had to create an account here to just warn others to never do what @lokiastari wrote. This is EXTREMELY dangerous! Either lokiastari is trolling this forum or is genuinely ignorant to their ways. I suspect the former because they were aware enough to understand how to write the command, but then again may not fully understand the syntax or commands themselves.
@lokiastari wrote:
--==AGAIN DON'T EVER RUN THIS COMMAND! YOU'VE BEEN WARNED!==--
(rm -rf . .* || echo "Delete * .* Done") 2> /dev/null
To break this command down:
rm - remove
-rf - recursive force (delete everything from my current location; force - a.k.a. don't ask to confirm, just do it; good so far as rm -rf is a common command that is frequently used - responsibly might I add)
. - current directory (you can't do this if you're in it - usually but not always)
.* - any hidden file (that starts with dot (.); this is bad because it includes too much including the current and parent directory)
|| - OR; this syntax is used to test the earlier command. Tangent: If a command succeeds you can run another command using && (i.e. IF TRUE) so long as the first command succeeds, but if it fails (OR else IF FALSE) then run another command, which in this case runs...
echo "Delete * .* Done" - Simply prints the statement 'Delete * .* Done' in the event of a failure. This fakes the user by oddly telling the user the delete is done, after it failed. (Don't know why you'd want to convince yourself that the failed command was done...?)
2> - redirect all stderr results...
/dev/null- to /dev/null; /dev/null is a way to void all output to nowhere (null), to avoid seeing the results (a.k.a. ignore errors)
All of this combined is a recipe for disaster because:
1. it explicitly is attempting to not only delete hidden dotfiles (i.e. .ignore, .fubar, .a, etc...) but...
2. it is also recursively attempting to delete the current directory (.)... (this isn't horrible but will fail because you're currently inside this directory)
3. ...along with the parent directory (.* <-- this means any file starting with a dot but including no or many characters, which in this case also includes the dot, therefore can also include dot dot (..) a.k.a. the parent directory.
4. all the while ignoring any failure responses by ignoring them
5. and intentionally covering up the errors by falsely claiming the remove was "Done" by providing a false positive message explicitly when it fails.
On the topic of && || control operators:
Just to further elaborate on the && || control operators, they're designed to be used when the first command either passes (&& - and do the next thing) or fails (|| - if failed, do this then). e.g. Command: ls && echo "command succeeded" || echo "command failed" Explained: This command lists the contents of the current directory and if it succeeds it will indicate so by printing the phrase "command succeeds". However, if for any reason it fails, it will instead print the phrase "command failed". So logic dictates that the command rm -rf . .* will fail, because you usually can't delete the current directory or it's parent since you currently reside in it's child path, and since it failed it will print the phrase "Delete * .* Done", giving the false impression that the delete completed successfully, even though it doesn't explicitly state "successfully" in the phrase, and people will infer.
The upside is that most systems are aware that you're attempting to delete the current directory you currently reside in and will usually not let you delete the parent folder, again because you're in a child folder at the time of issuing the command. But there are forceful ways this can be done and if the OS isn't smart enough will let this happen.
The original answer is the absolute correct response because it explicitly avoids . and .. via glob patterns.