Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I have a folder structure like this.

folders
    test1
    test2.1
    test49.85
    test4.95.89
    sample
    support
    util

These are all folders. I need to delete all folders that begin with test, except the most recent one. I do have access to the folder name of the most recent ${newestTestFolder} also.

Thanks.

share|improve this question
    
What operating system? –  user3463 Aug 23 '12 at 16:55
    
The os is centos 5.3 –  yellavon Aug 23 '12 at 16:56

2 Answers 2

up vote 4 down vote accepted

Using extglob in Bash:

$ ls -1
sample
support
test1
test2.1
test4.95.89
test49.85
util
$ newestTestFolder="test49.85"
$ shopt -s extglob
$ ls -d1 !(@(${newestTestFolder}|!(test*)))
test1
test2.1
test4.95.89

This shows that

$ rm -r !(@(${newestTestFolder}|!(test*)))

does what you want in a single command all within Bash (with extglob enabled) - no extra process invocations (well, rm).

The pattern is explained in the Bash manual and means

  • !() - not the pattern within
  • @() - one of the patterns within
  • | - separates patterns
share|improve this answer
    
nice. but i guess it involves setting newest folder name manually? and you have deleted only the newest one instead of leaving only this one - but this is of course a detail.. –  mnmnc Aug 23 '12 at 17:33
    
@mnmnc: Yes, this does not look at timestamps at all. The question said that the name was available in a variable. No, I'm deleting the old test* directories with this command. The same directories that are shown with the last ls command in the first section are the ones that should be deleted with the later shown rm command. –  Daniel Andersson Aug 23 '12 at 17:43
    
When running ls -d1 !(@(${newestTestFolder}|!(test*))) I get -bash: !: event not found I tried escaping with \ but then i get unexpected token ( –  yellavon Aug 23 '12 at 18:16
    
@yellavon: Did you enable extglob as shown? Issue shopt -s extglob. For that matter - are you using Bash? Otherwise it will not work :-) –  Daniel Andersson Aug 23 '12 at 18:28
    
Yeah, I just needed to enable extglob. Thanks. –  yellavon Mar 12 '13 at 21:33

Use this: (I have changed it to grep only the folders that begins with test)

for i in `\ls -1 --sort time | grep ^test | tr '\n' ' ' | cut -d " " -f 2-`; 
do 
     rm -r "$i"; 
done

yep. Works for me:

 ~ > ls
total 24
drwxr-xr-x 3 root root 4096 2012-08-23 01:08 Dev
drwxr-xr-x 2 root root 4096 2012-08-24 18:50 latest
drwxr-xr-x 2 root root 4096 2012-08-24 19:14 test1
drwxr-xr-x 2 root root 4096 2012-08-24 19:14 test2
drwxr-xr-x 2 root root 4096 2012-08-24 19:14 test3
drwxr-xr-x 2 root root 4096 2012-08-24 19:14 test4
 ~ > for i in `\ls -1 --sort time | grep ^test | tr '\n' ' ' | cut -d " " -f 2-`;
>     do
>          rm -r "$i";
>     done
 ~ > ls
total 12
drwxr-xr-x 3 root root 4096 2012-08-23 01:08 Dev
drwxr-xr-x 2 root root 4096 2012-08-24 18:50 latest
drwxr-xr-x 2 root root 4096 2012-08-24 19:14 test4
 ~ >

The ones that are left is the youngest folder and folder that not matches test My version is universal - you do not need to provide the name of youngest test folder.

And regarding comment below - you can use following line in for expression

\ls -1 --sort time | grep ^test | tr ' ' '#' | tr '\n' ' ' | cut -d " " -f 2- | tr '#' ' '

if you are expecting to have spaces in folder names. I did used # as an uncommon character unlikely to be in folder names. You can use other if you will expect to have either spaces or # characters. You can change # to combination of characters to limit the risk.

Proof it's working:

 ~ > ls
total 36
drwxr-xr-x 3 root root 4096 2012-08-23 01:08 Dev
drwxr-xr-x 2 root root 4096 2012-08-24 18:50 latest
drwxr-xr-x 2 root root 4096 2012-08-24 19:19 test
drwxr-xr-x 2 root root 4096 2012-08-24 19:19 test1
drwxr-xr-x 2 root root 4096 2012-08-24 19:19 test2
drwxr-xr-x 2 root root 4096 2012-08-24 19:19 test3
drwxr-xr-x 2 root root 4096 2012-08-24 19:20 test 4
drwxr-xr-x 2 root root 4096 2012-08-24 19:20 test5
drwxr-xr-x 2 root root 4096 2012-08-24 19:21 test 6
 ~ > for i in `\ls -1 --sort time | grep ^test | tr ' ' '#' | tr '\n' ' ' | cut -d " " -f 2- | tr '#' ' '`;
>     do
>          rm -r "$i";
>     done
 ~ > ls
total 12
drwxr-xr-x 3 root root 4096 2012-08-23 01:08 Dev
drwxr-xr-x 2 root root 4096 2012-08-24 18:50 latest
drwxr-xr-x 2 root root 4096 2012-08-24 19:21 test 6
 ~ >
share|improve this answer
1  
This will fail if there are directories with spaces in them. Also, it will not ignore directories named e.g. latest, i.e. not starting with test. –  Daniel Andersson Aug 23 '12 at 17:37
    
@DanielAndersson i've updated my answer. Its foolproof againt spaces in folder names and it will not delete folders like latest –  mnmnc Aug 24 '12 at 17:37

Your Answer

 
discard

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.