Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Suppose under the current directory, there are multiple sub-directories, and one is called A.

How to delete all sub-directories except A with Bash?

share|improve this question
add comment

9 Answers 9

Bash has extended globbing (first test, then remove the echo):

shopt -s extglob
echo rm -rf !(A)
share|improve this answer
    
(before I forget - you might disable CSH style history completion, in Bash3 there's a bug while ignoring !(. set +H –  TheBonsai Jun 4 '09 at 19:38
    
+1 Bash if full of surprises! Sometimes they are nice like this one. –  Aleksandr Levchuk Nov 16 '10 at 1:46
add comment
find -maxdepth 1 -type d -not -name A -not -name "." -exec rm -ir {} \;
share|improve this answer
3  
wtf community wiki? –  dotjoe Jun 4 '09 at 21:31
add comment

Something like

find . -type d -not -name A -exec rm -ir {} \;

should do.

edit

It should really be

find . -type d -maxdepth 1 -not -name A -exec rm -ir {} \;

to prevent find from recursing below A.

share|improve this answer
3  
But, this would also remove any sub-directories below A like A/foo and A/bar, but would preserve A/A. –  TCampbell Jun 4 '09 at 19:30
    
Cool! Questions and answert get migrated from SO to SF... but my edit above was lost... –  agnul Jun 4 '09 at 19:47
add comment

What about:

mv A /tmp/
rm * -rf
mv /tmp/A .

This avoids some of the "scariness" of a typo in the other commands.

share|improve this answer
1  
+1 for doing the sane thing instead of hoping the tools are smart enough. still, one night, when i was just learning Linux, i copied the kernel to /tmp before doing my first recompile. it didn't succeed, but erased the old one, so i said 'no sweat, i have a copy' only to find that a midnight cron task had erased it with every file more than a week old in /tmp! i had to recompile again and this time do it right, or no reboot for me! –  Javier Jun 4 '09 at 21:16
    
best answer posted :) –  warren Nov 16 '10 at 2:59
add comment

i usually do this by working up an ls command that gets it right first. i'm not at a unix machine, but something like:

ls -lda "[^A]"

Once you get it right, pipe it to a command

ls -lda "[^A]" | xargs rm -rf

Feel free to edit above if I've got my regular expression wrong...

share|improve this answer
    
You shouldn't parse ls: mywiki.wooledge.org/ParsingLs –  Dennis Williamson Jun 4 '09 at 22:41
add comment

If you want to be more flexible but manual you can do:

ls > /tmp/foo
edit /tmp/foo as you like
xargs -a /tmp/foo rm -r

That way you can do general munging.

share|improve this answer
add comment

Here's one way. Be careful with this sort of thing, though, it's so powerful that it can only be used for good or evil...

find * -type d | grep -v "^A" | xargs rm -rf
share|improve this answer
add comment

Don't use find as some people have shown with -exec and rm without passing -print0 to find and -0 to xargs. It will get confused on file names with spaces or newlines:

$ mkdir 'foo foo'
$ mkdir foo$'\n'foo 
$ find . -type d -exec rm -ir {} \;
rm: cannot remove directory `.'
rm: remove directory `./foo\nfoo'? y
find: `./foo\nfoo': No such file or directory
rm: remove directory `./foo foo'? y
find: `./foo foo': No such file or directory

Instead use find -print0 with xargs -0 , '-exec command {} +', or -delete if your find supports it.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.