0

Source path:

/var/log/

Here I have 4 folders named ad1nrld,ad2nrld,icp1rmnrl,icp2rmnrl

I can move all the files to the other destination named /home/spsy/logs_bkp. But I want to keep latest 5 files in each folders (ad1nrld,ad2nrld,icp1rmnrl,icp2rmnrl) of this /var/log path and rest will be moved to /home/spsy/logs_bkp path.

At source path, /var/log/ad1nrld - Only latest 5 files will be present and rest will be moved to /home/spsy/logs_bkp/ad1nrld path

I have tried the below code for moving the files and they are successfully moved. But I am unable to keep latest 5 files in the respective folders.

for i in `ls -1rt | egrep 'nrld|mnrl'`
do
cd $i
mv *log /home/spsy/logs_bkp/$i
echo "files moved for &i"
cd ..
done

The below part is not working while I am adding the code to keep latest 5 files.

for i in `ls -1rt | egrep 'nrld|mnrl'`
do
cd $i
count_files=`ls -lrt | wc -l`
if [ $count_files -gt 5 ];
then
tomove=$(($count_files-5))
for part in `ls -1rt`
do
if [ $tomove -gt 0 ]
then
mv $part /home/spsy/logs_bkp/$i
tomove=$(($tomove-1))
echo "files moved for &i"
cd ..
fi
done
fi
done
Nainita
  • 2,862

3 Answers3

3

zsh is generally available on Solaris unless you installed a stripped down version of it, so you should be able to do:

#! /usr/bin/zsh -
src=/var/log dst=/home/spsy/logs_bkp
dirs=(ad1nrld ad2nrld icp1rmnrl icp2rmnrl)

ret=0 for dir ($dirs) () { if (( $# > 5 )) mv -- $@[6,-1] $dst/$dir/ || ret=$? } $src/$dir/*(N.om) exit $ret

That uses the om glob qualifier to order the glob expansion (only regular files with the . qualifier) by modification time (from youngest to oldest like ls -t does). Add the D qualifier if you also want to consider hidden files.

That glob expansion is passed to an anonymous function which moves the 6th to last files as long as there are more than 5 in the directory, doing it for each $dir in $dirs.

With ksh or other shells, without glob qualifiers the difficult part is to order the list of files by modification time and restrict to regular files only.

ls -t will sort by modification time, but you can't easily reconstruct the list of files from its output unless you can guarantee file names won't contain newline characters. If you're in such a special case, you can do:

#! /bin/sh -
src=/var/log dst=/home/spsy/logs_bkp
dirs='ad1nrld
ad2nrld
icp1rmnrl
icp2rmnrl'

IFS=' ' # split on newline only set -o noglob # disable globbing so we can use split+glob to split.

ret=0 for dir in $dirs; do # split+glob to split $dirs set -- for file in $(ls -t -- "$src/$dir/"); do # split+glob to split ls output [ -f "$file" ] && [ ! -L "$file" ] && set -- "$@" "$src/$dir/$file" done if [ "$#" -gt 5 ]; then shift 5 mv -- "$@" "$dst/$dir/" || ret="$?" fi done exit "$ret"

1

Version, that does not rely on parsing ls, but uses find and \0 as line terminator:

(As you're using Solaris, and this uses GNU extensions, this might not be possible for you, but might be useful for others).

dirs=(ad1nrld ad2nrld icp1rmnrl icp2rmnrl)
for dir in "${dirs[@]}"; do
    find "$dir" -maxdepth 1 -type f -printf '%T@\t%p\0' \
      | sort -rnz \
      | tail -z -n+6 \
      | cut -z -f2- \
      | xargs -r0 mv --backup=numbered -t logs_bkp/
done
pLumo
  • 22,565
0

Script is working. I have 4 folders named ad1nrld,ad2nrld,icp1rmnrl,icp2rmnrl in /var/log path. Script will keep latest 5files in the respective folders and rest will be moved to the respective folders of the /home/spsy/logs_bkp path.

This is the code.

cd /var/log
for i in `ls -1rt | egrep 'nrld|mnrl'`
do
cd $i
count_files=`ls -lrt | wc -l`
if [ $count_files -gt 6 ];
then
tomove=$(($count_files-6))
for part in `ls -1rt`
do
if [ $tomove -gt 0 ]
then
mv $part /home/spsy/logs_bkp/$i
tomove=$(($tomove-1))
fi
done
cd ..
fi
done
Nainita
  • 2,862
  • See https://unix.stackexchange.com/questions/68694 (about quoting), and https://unix.stackexchange.com/questions/128985 (about ls). I'm also wondering why you use ls with egrep in your outer loop when you know the exact names of the directories that you want to loop over? – Kusalananda Feb 24 '22 at 07:00
  • You should consider indenting your code blocks to improve readability. Also make sure your variables are always inside double quotes when you use them. Remember to put a #!/bin/sh at the top of the file (first line) to show the system that you've written this script in sh. – Chris Davies Feb 24 '22 at 07:27
  • This will break if any file name contains spaces. If this can be guaranteed not to happen then you're reasonably safe – Chris Davies Feb 24 '22 at 07:32
  • Yes..It is guaranteed that file names are stored in a predefined manner and won't change in future. Also Shebang is added in the script as it will be executed from the crontab itself. – Nainita Feb 24 '22 at 07:36