> unicorn:~$ mkdir /tmp/x && cd "$_" > unicorn:/tmp/x$ mkdir 98 99 100 101 102 103 104 > unicorn:/tmp/x$ echo * > 100 101 102 103 104 98 99
Hello Gred Very thanks. Worked :) Best regards... On Tue, Oct 12, 2021 at 7:04 PM Greg Wooledge <g...@wooledge.org> wrote: > > On Tue, Oct 12, 2021 at 05:41:59PM +0300, Gokan Atmaca wrote: > > I have directories created at different times. This last updated > > directory is in the directory with a symbolic link named "last". > > Directories are named from 100 to 110. what i want is to delete all > > directories except the folder named "last" and 4 before it. How can I > > do that? > > > > Exampe_folder_list: > > 100 > > 101 > > 102 > > 103 > > 104 > > 105 > > 106 > > 107 > > 108 > > 109 > > 110 > > last -> /root/test1/110 > > I have a serious problem with this example: it doesn't show what happens > when the number of digits changes. What if the first (oldest) directory > were number 99 instead of 100? Would it be named "99", or would it be > named "099"? When you get to directory number 1000, is there going to > be another change in the number of digits? > > Because of this ambiguity, we have to assume the *worst* case, which is > that the number of digits changes over time. The directory names will > be "99", "1000", and so on. Not a fixed length. > > Why does this matter? Because when you list the directory names and sort > them by name, you will get a mangled sequence: > > unicorn:~$ mkdir /tmp/x && cd "$_" > unicorn:/tmp/x$ mkdir 98 99 100 101 102 103 104 > unicorn:/tmp/x$ echo * > 100 101 102 103 104 98 99 > > The names are sorted lexicographically, not numerically. So, the simplest > approaches are NOT permitted. They will fail. > > What does that leave? Well, the more complicated approaches, of course. > > If we believe Gokan's assertion that the directory names will always be > strictly numeric, or the word "last", then we can use "sort -n" to get > them in sequence. > > unicorn:/tmp/x$ printf '%s\n' * | sort -n > 98 > 99 > 100 > 101 > 102 > 103 > 104 > > >From there, it becomes pretty straightforward. We read these names into > an array, and process all except the last 4. > > Here's one way to do that: > > unicorn:/tmp/x$ mapfile -t dirs < <(printf '%s\n' * | sort -n) > unicorn:/tmp/x$ n=${#dirs[@]} > unicorn:/tmp/x$ echo "${dirs[@]:0:n-4}" > 98 99 100 > > The dirs array holds all of the names. We count how many there are, and > then process "all but 4" of them, starting from element 0. In my example, > there are 7 directory names, so we process 3 of them. > > We also want to avoid processing "last", so we probably want a glob other > than * for our input. We could get fancy and use an extended glob like > !(last) -- or we could simply use [0-9]* to match only the names that > begin with a digit. In the interest of simplicity, let's do the second > thing. > > So, the script might look something like this: > > > #!/bin/bash > cd /wherever || exit 1 > mapfile -t dirs < <(printf '%s\n' [0-9]* | sort -n) > n=${#dirs[@]} > echo rm -rf "${dirs[@]:0:n-4}" > > > This will *print* a command instead of running it. If you test it and > see that the command looks sensible, then change "echo rm" to "rm" and > voila. >