How to delete only directories and leave files untouched
Asked Answered
Q

8

91

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

Quizzical answered 10/5, 2011 at 16:19 Comment(0)
G
-19

In one line:

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

(backquotes)

Grigsby answered 10/5, 2011 at 16:28 Comment(3)
Don't pipe the output from ls; especially not to rm -r. It fails when pathnames contain spaces.Coralyn
Did not consider the space issue. Will remember that.Grigsby
Much more recommended and simple this answerSymposiarch
B
266

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.

Bowline answered 12/7, 2011 at 17:4 Comment(11)
to skip y/n questions: rm -rf */Attach
Keep in mind expansion when using this in a script, as asterisks will not expand in quotes. As is, it should work fine. unix.stackexchange.com/questions/156534/…Catfall
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 optionTricuspid
@Gi0rgi0s: I upvoted your sentiment, but rm -rf ./*/ is also only one character away from rm -rf /*/Yorker
@Yorker 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 thisThirteen
@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.Yorker
There is nothing about "/" flag on the man page of rm. Where can I read more about it?Palpable
@JerzyBrzóska It is a bash wildcard and I have added a note to the answerBowline
"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.Philibeg
Can check with ls */ that it returns directories and subdirectories. It is also how bash globstar is described, see shopt globstar and Pattern-MatchingBowline
(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 …" (2) globstar is irrelevant because it affects how ** is interpreted, not *. Your answer does not contain ** (not that it should).Philibeg
N
41

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

Nefen answered 14/4, 2016 at 11:24 Comment(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.Frostbitten
T
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.

Thorrlow answered 10/5, 2011 at 16:24 Comment(3)
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 -typeScholar
@Scholar you have an extra hyphen in there. It should be find /path -d -type dWolters
awesome answer!Bargain
S
2

Simple way :-

rm -rf `ls -d */`
Sibert answered 6/10, 2019 at 18:6 Comment(1)
As others have commented, this won't work if your directory names contain spaces.Drysalt
G
1

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

Geaghan answered 21/5, 2023 at 15:33 Comment(1)
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.Eloquent
P
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

Piranesi answered 22/2, 2022 at 20:38 Comment(0)
D
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.

Dahna answered 30/5, 2023 at 20:24 Comment(0)
G
-19

In one line:

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

(backquotes)

Grigsby answered 10/5, 2011 at 16:28 Comment(3)
Don't pipe the output from ls; especially not to rm -r. It fails when pathnames contain spaces.Coralyn
Did not consider the space issue. Will remember that.Grigsby
Much more recommended and simple this answerSymposiarch

© 2022 - 2024 — McMap. All rights reserved.