Soup To Nuts

 Bash 
 
Common Commands:
 
Testing the success of failure of the last command.
test 34 -gt 23
echo $?
  0
test 34 -lt 23
echo $?
  1
Getting the process id, parent id and the command
ps -e -o pid,ppid,command
Backup currently dir contents to remote server 130.91.97.45, /home/user1/junk2/user1backup.tgz
tar zcvf - .| ssh user1@130.91.97.45 "cat > /home/user1/junk2/user1backup.tgz"
List only directories
find . -type d -maxdepth 1
or
ls -d */.
                       
Question:  Log files are created based on the amount of activity.  Some days, 4 to 7 log files may be created, other days no log files are created.  It's all based upon the amount of activity.
 
How is it possible to create a script that will delete all the logs that are >  3 days old.  However, if no log files have been written in the last several day, then, save the most recent 3, even if they are older than "n" days.   
 
 remove_old_log_files  
 
#!/bin/bash
#
#  Only keep the most recent NUMLOGS log files
#  that haven't changed status the last n*24 hours
#
#  The find command finds all '*.log' files  
#      "-ctime +n" for files change status > n*24
#      "-maxdepth 1" only search the current directory
#      "-type f" standard files
#      "-printf "%A@" returns seconds since Jan 1, 1970
#
#  Sort does just that ... sort
#
#  awk gets count > NUMLOGS and prints
#     the name plus the path

# User defined variables
LOGFILE='*.c'
NUMLOGS=2
CTIME='+3'  # n*24 hours
#
#
for i in `find . -ctime "${CTIME}" -type f -maxdepth 1 -name "${LOGFILE}"  -printf "%A@ %p\n" 2>/dev/null|sort |awk 'NR > '"${NUMLOGS}"' {print $2}'`
do
        echo $i;
        # Change echo to rm $i once you're convinced it works
done

 
 
 
 
Find and Replace: Find and replace mchirico@med.upenn.edu with mchirico@users.sourceforge.net , assuming some of the files and or directories contain spaces.  Furthermore, don't replace if the file is under a CVS directory, contains a '~',or '#'.  Also, keep a log of all the replacements.  A special note, if the while read was used, the count variable would be created in a child process.  Thus, it would not get updated correctly in the final output.  Also, be careful when using continue statements as well. 
 

 mreplace  
#!/bin/bash
#  Copyright (C) 2003  Mike Chirico mmc mchirico@users.sourceforge.net GPL
#	Sample bash program to replace contents in files
#

#
NoReplace_just_look=true
#
findstr='mchirico@med.upenn.edu'
replacestr='mchirico@users.sourceforge.net'
fileToListAllreplacements='/home/chirico/mreplace_log'


#
# find that ignores directory names; but, searches sub directories
# ignore CVS directories and this filename mreplace

# 
if [ -f $fileToListAllreplacements ]
then
    echo "************" >> $fileToListAllreplacements
    echo `date` >> $fileToListAllreplacements

fi
count=0
#needed to handle tabs and spaces
IFS=$'\n'
# nothing in a CVS directory, or a file with ~ or #
for i in `find . -name  '*' -type f  |grep -v 'CVS'|grep -v 'mreplace'| grep -v $fileToListAllreplacements | grep -v '~' | grep -v '#' `
# Don't use this: read commands in the shell create a new environment.  Yes, it will work to find the files
# but the count will be off because it will not be passed to the new environment. Also, becareful with a contiue statement as well
#find . -name  '*' -type f  |grep -v 'CVS'|grep -v 'mreplace'| grep -v $fileToListAllreplacements | grep -v '~' | grep -v '#' | while read  i
#

do

  if  grep -q  $findstr $i; then
# uncomment to list what is relaced and the filename
#      grep -l $findstr $i|xargs -l1  awk '{print substr($0,0,30)}'  >> $fileToListAllreplacements
      echo $i >> $fileToListAllreplacements
      if [ $NoReplace_just_look ]
       then
	  echo $i
       else
	  sed -e "s/$findstr/$replacestr/g" $i > $i.tmp && mv $i.tmp $i
       fi
      let count=$count+1

  fi
done
if [ $NoReplace_just_look ]
then
    echo "$count files found"
else
    echo "$count replacements made"
fi

 
Sample Program:
#!/bin/bash
# created mmc mchirico@users.sourceforge.net CopyRight 2003 GPL
# version 0.0.1b
#
# Creates a tar.gz file of all files after copying them
# into the $tarfile directory
# 
# If you want to auto-upload to sourceforge
# You'll need a .netrc with the following lines:
#      machine upload.sourceforge.net login anonymous password m@aol.com
# Then, if executed with a parameter ./myMakeTar 1
# will upload the file to sourceforge
#
#
tarfile="bashscripts.0.0.1b"
if [ -d $tarfile ]
then
  echo "Directory $tarfile exist" 
else
    mkdir $tarfile
fi
t=""
for i in `find .  -maxdepth 1 -iname '*' `
do
	case "$i" in
	"./CVS" ) continue;;
	"$0" ) continue;;
	*~ ) continue;;
	"./${tarfile}.tar.gz" ) continue;;    
	"./${tarfile}.tar" ) continue;;    
	"./${tarfile}" ) continue;;
	"./${tarfile:0:${#tarfile}-5}"* ) continue;;
	* ) t="${i} ${t}"; cp $i $tarfile/. ;;
	esac

done
tar -czf $tarfile".tar.gz" $tarfile

NOARGS=1
if [ -z $1 ]
then
    echo "  To upload file to sourceforge: `basename $0 ` 1"
    exit
else
# You'll need a ~.netrc with the following lines
# machine upload.sourceforge.net login anonymous password m@aol.com
    ftp << FTPSTRING
open upload.sourceforge.net 
cd incoming
put ${tarfile}.tar.gz
bye
FTPSTRING


fi




 
diff and patch:  Useful for creating a patch to distribute to users.  Example below.
 
diff -c test1.c test2.c > test1_to_test2.patch
patch < test1_to_test2.patch
 
 
 

 
More samples can be found in the download.


 
Changes
12.08.03 remove_old_log_files
8.06.03 Fixed problems in mreplace
8.05.03  Added (mreplace) Find and Replace
7.25.03  Updated text  
 
 
 
SourceForge.net Logo