86

I have hundreds of directories and files in one directory.

What is the best way deleting only directories (no matter if the directories have anything in it or not, just delete them all)

Currently I use ls -1 -d */, and record them in a file, and do sed, and then run it. It rather long way. I'm looking for better way deleting only directories

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
kopelkan
  • 1,135
  • 2
  • 9
  • 8

8 Answers8

259

To delete all directories and subdirectories and leave only files in the working directory, I have found this concise command works for me:

rm -r */

It makes use of bash wildcard */ where star followed by slash will match only directories and subdirectories.

Cas
  • 6,123
  • 3
  • 36
  • 35
  • 18
    to skip y/n questions: rm -rf */ – Daniel Nuriyev Dec 10 '14 at 22:32
  • 1
    Keep in mind expansion when using this in a script, as asterisks will not expand in quotes. As is, it should work fine. http://unix.stackexchange.com/questions/156534/bash-script-error-with-strings-with-paths-that-have-spaces-and-wildcards – Ray Foss Nov 02 '15 at 14:29
  • 2
    This is the most highly voted answer but I was testing this out because I am trying to do the same thing but I think this answer just deletes everything and doesn't do what the original question is asking. Take care when using it. Catalint/Jeremy's profile answer does a better job of addressing the question, at least for me. My case was that I have some folders containing files I want to keep but also a bunch of empty junk folders I want to delete so a command based on ```find . -maxdepth 1 -mindepth 1 -type d``` is a better option – julianhatwell Nov 11 '19 at 08:43
  • 1
    @Gi0rgi0s: I upvoted your sentiment, but `rm -rf ./*/` is _also_ only one character away from `rm -rf /*/` – poleguy Jan 08 '20 at 20:38
  • @poleguy yup, I will delete that comment. For some reason it seems more safe though. I have deleted the comment that suggested `rm -rf ./*/` maybe there's a better way to do this – Gi0rgi0s Jan 08 '20 at 22:57
  • @Gi0rgio0s, well, it is more characters so it does give you a bit more time to think about what you're doing. :-) I think the key thing is to recognize the risk, so the comment of being one off from a really bad `rm -rf /` type command is a good comment to leave with the answer. – poleguy Jan 09 '20 at 23:23
  • There is nothing about "/" flag on the man page of rm. Where can I read more about it? – John Smith Aug 07 '20 at 08:24
  • 1
    @JerzyBrzóska It is a bash wildcard and I have added a note to the answer – Cas Aug 07 '20 at 11:31
  • "bash wildcard `*/` where star followed by slash will match only directories and subdirectories" – Directories in the current working directory, yes, but *not* subdirectories. Subdirectories will be deleted because of `-r`, not because the wildcard matches them. By default `*` does not match dot files. – Kamil Maciorowski May 26 '23 at 19:45
  • 1
    Can check with `ls */` that it returns directories and subdirectories. It is also how bash globstar is described, see [shopt globstar](https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html) and [Pattern-Matching](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html) – Cas May 27 '23 at 08:24
  • 1
    (1) For an operand being a directory, `ls` will show its content (unless `-d` is used), so you will see names of files (including directories) one level deeper than the operand. E.g. `ls /` does show `etc`. But this is how `ls` works, not `*/`. Check with `echo */`. "[When matching a filename, the slash character must always be matched explicitly by a slash in the pattern, but …](https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html)" (2) `globstar` is irrelevant because it affects how `**` is interpreted, not `*`. Your answer does not contain `**` (not that it should). – Kamil Maciorowski May 27 '23 at 08:42
38

find . -maxdepth 1 -mindepth 1 -type d

then

find . -maxdepth 1 -mindepth 1 -type d -exec rm -rf '{}' \;

To add an explanation:

find starts in the current directory due to . and stays within the current directory only with -maxdepth and -mindepth both set to 1. -type d tells find to only match on things that are directories.

find also has an -exec flag that can pass its results to another function, in this case rm. the '{}' \; is the way these results are passed. See this answer for a more complete explanation of what {} and \; do

jeremysprofile
  • 10,028
  • 4
  • 33
  • 53
catalint
  • 1,895
  • 17
  • 17
  • 1
    Although this code may answer the question, providing additional context regarding _why_ and/or _how_ it answers the question would significantly improve its long-term value. Please [edit] your answer to add some explanation. – Toby Speight Apr 15 '16 at 16:17
13

First, run:

find /path -d -type d

to make sure the output looks sane, then:

find /path -d -type d -exec rm -rf '{}' \;

-type d looks only for directories, then -d makes sure to put child directories before the parent.

onteria_
  • 68,181
  • 7
  • 71
  • 64
  • The first command doesn't even work for me. > find . -d -type -d find: warning: the -d option is deprecated; please use -depth instead, because the latter is a POSIX-compliant feature. find: invalid argument -d to -type – Anthony Jan 29 '14 at 18:30
  • 1
    @Anthony you have an extra hyphen in there. It should be `find /path -d -type d` – csvan Apr 19 '16 at 15:00
  • awesome answer! – 陳子軼 Jul 23 '19 at 16:49
2

Simple way :-

rm -rf `ls -d */`
Kuldeep Darmwal
  • 185
  • 1
  • 2
  • 9
0

find command only (it support file deletion)\

find /path -depth -type d -delete

-type d looks only for directories, then -depth makes sure to put child directories before the parent. -delete removing filtered files/folders

demon101
  • 544
  • 1
  • 11
  • 39
0

rm -R $(ls -1 -d */ | grep .. )

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 21 '23 at 18:27
0

I have done this, by adding a way to preserve one folder. I execute the command in a subfolder for removing folders in the parent one. It doesn't work for directory names with spaces:

  • parent folder => CleanTheSystem

  • subfolder_to_be_preserved => Linux

  • file in the subfolder_to_be_preserved => OK_Mackay.txt
    
  • subfolder_to_delete => Windows

  • too_many_files => ***
    
    
     rm -r $(ls -1 -d ../*/ | grep -v Linux);
    

    And this works for folder names with spaces:

     find ../. -type d -name "* *" -execdir bash -c 'mv "$1" "${1// /_}"' _ {} \; 2>/dev/null;rm -r $(ls -1 -d ../*/ | grep -v Linux);
    

Warning!: Be careful. If you misspell Linux, everything will be erased.

clarke
  • 21
  • 2
-19

In one line:

rm -R `ls -1 -d */`

(backquotes)

Mouse Food
  • 231
  • 3
  • 9