> 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.
>

Reply via email to