You have a loop that tests a certain condition based on two variables that you never change. I'm assuming you were meaning to decrease the NUMSNAPS value by one in each iteration.
In the zsh shell, you may do
retain=2
rm -f while/*(DN.Om[retain+1,-1])
to delete all regular files (including files with hidden names) apart from the $retain most recently modified files. If this happens to be several thousands of files, you may want to use zargs instead:
retain=2
autoload -U zargs
zargs -- while/*(DN.Om[retain+1,-1]) -- rm
If you want to order the files by name instead, then replace Om ("order by mtime timestamp, in decreasing order") by On ("order by name, in decreasing order").
You could obviously call this from another shell than zsh by using e.g.
retain=2
zsh -c 'rm -f $2/*(DN.Om[$1+1,-1])' zsh "$retain" "while"
This also passes the name of the directory and the number of files to retain into the in-line script, making it easier to incorporate into an existing non-zsh script.
In the bash shell, you don't really want to parse the output of ls. Instead you may want to use
shopt -s dotglob nullglob
retain=2
set -- while/*
while [ "$#" -gt "$retain" ]; do
rm -f "$1"
shift
done
This would set the list of positional parameters to the list of files in the while directory (including hidden names), and then remove files form that list until there are only retain files left in the list.
This avoids issues with awkward filenames, and it also avoids calling ls once for every file removed.
This code would delete files based on their names (not by last-modified timestamp). This seems to be what your code is also attempting to do.
NUMSNAPSinside the loop. – kaylum Jan 02 '20 at 23:09