tags:

views:

307

answers:

5

How would you do this in bash

+6  A: 
ls -atrd */ | head --lines=-4 | xargs rm -rf

Edit: added 'a' argument to ls

Leigh Caldwell
this will leave 4 most recently modified directories instead of the 4 most recently created, won't notice directories starting with a dot, head will break for names containing newlines, xargs will break for names containing whitespace, and rm will print an error message if there's nothing to delete.
Alexey Feldgendler
Good points. I have now added 'a' to ls to capture directories with a dot, and grepped to get rid of the current and parent directories, but you're right. This is a simple answer with some important limitations as you have pointed out.
Leigh Caldwell
Correction: no grep is needed to filter the current and parent directory as they are not shown by ls */
Leigh Caldwell
+1  A: 

Please clarify if you mean “delete all directories but the four newst ones” or “delete everything (files and directories) except for the four newest directories”.

Please also note that creation times are not known for directories. One can only tell when a directory was last modified, that is, had files added, removed or renamed.

Alexey Feldgendler
+1  A: 

you could do the following:

#!/bin/bash

#store the listing of current directory in var
mydir=`ls -t`
it=1

for file in $mydir
    do
        if [ $it -gt 5 ]
        then
            echo file $it will be deleted: $file
            #rm -rf $file
        fi
        it=$((it+1))
    done

(remove the # before rm to make it really happen ;) )

mana
A: 

Another, BSD-safe, way to do it, with arrays (why not?)

#!/bin/bash
ARRAY=( `ls -td */` )
ELEMENTS=${#ARRAY[@]}
COUNTER=4
while [ $COUNTER -lt $ELEMENTS ]; do
  echo ${ARRAY[${COUNTER}]}
  let COUNTER=COUNTER+1
done
mdxi
A: 

ls -trd */ | head --lines=-4 | xargs rm -rf works perfectly, thanks - these directories are only created and written to once, so there's no difference between ctime and mtime, but good point Alexey

eventi