I have a directory containing files of the following name structure.


I am working on a script that will retain the the last X copies of these configuration backups per each device. What kind of select magic do I need in order to make this happen?

I was thinking BASH but I'm really language agnostic.

3 Answers 3


Wildcards expand file names in lexicographic order. Since your date format matches lexicographic order, your requirement boils down to retaining the last X matches for a wildcard (or all matches if there are fewer than X). I'll assume that your backups are the files matching $device.*, adjust the pattern as needed.

In zsh:

set -- $device.*
if [[ $# -gt $X ]]; then set -- $@{[-$X,-1]}; fi
cp -- $@ /retain/area/

In any Bourne-style shell (ash, bash, ksh, …):

set -- "$device".*
if [ $# -gt $X ]; then shift $(($#-$X)); fi
cp -- "$@" /retain/area

If what you want is in fact to remove older files, you need to act on the first matches but X (or no matches if there are fewer than X).

In zsh:

rm -f -- $files[1,-$X-1]

In other shells:

set -- "$device".*
while [ $# -gt $X ]; do
  rm -- "$1"

Taking advantage of your file names, and that ls sorts lexically by default:

ls | awk -F . '
    $1 != current_device {
        current_device = $1
        n5[$1] = n4[$1]
        n4[$1] = n3[$1]
        n3[$1] = n2[$1]
        n2[$1] = n1[$1]
        n1[$1] = $0
    END {
        for (device in n1) {
            print n1[device]
            print n2[device]
            print n3[device]
            print n4[device]
            print n5[device]

I assume the device names do not contain dots. Results likely won't be sorted


May need some changes but:

ls <DEVICE>.* | sort -r | tail -n +<X+1> | xargs echo rm 

That will output the rm statement, remove the "echo" to just delete directly.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .