Find the answer to your Linux question:
Results 1 to 7 of 7
I need to compare two files. I know this sounds easy but the way I have to create the two files is confusing me. The code that I have is: ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Jan 2013
    Posts
    9

    Bash Script comparing two files


    I need to compare two files. I know this sounds easy but the way I have to create the two files is confusing me.

    The code that I have is:

    Code:
    while [ $COUNT -gt 0 ]; do
    	echo "DATE: $CURRENT">> spy.txt
    	
    	ps axo user,pid,comm >> spy.txt  #run command ps to list all process and append it to thelog file
    	
    echo " "
    	
    echo " " > temp.txt
    
    grep DATE spy.txt >> temp.txt
    for array in ${array[at symbol]} #it will not let me post with the actual at symbol
    do
        grep "$array" spy.txt >> temp.txt
    done
    	let COUNT=COUNT-1 #count down mechanism for loop
    	sleep $TIME  #argument to wait so many seconds between iterationso fo main loop
    done
    For each time the loop is called the ps command is run and sent to a file spy.txt, then I take the array of strings and grep spy.txt to see if there is a specific process run by a user, or if a particular process is running.
    Now the next part of what I need to do is each time the while loop runs for COUNT I need to compare the last scan that is sent to temp.txt with the new scan and send the output to a file. Now I do not know how to do this. Do I need to copy temp.txt to a different file before the loop runs again and compare the copy of temp.txt with the new temp.txt?
    Is there an easier way of doing this that I am missing?

  2. #2
    Just Joined! mrbruno's Avatar
    Join Date
    Jan 2013
    Location
    /MilkyWay/Sol/Earth/USA/NC/Raleigh
    Posts
    66
    I'm having trouble following what you're trying to do. Can you provide an example to describe your objective in terms of expected output?

  3. #3
    Just Joined!
    Join Date
    Jan 2013
    Posts
    9
    Ok the first goal is to create a list of processes :

    dresden0526 4325 bash
    dresden0526 ps axo

    Then the program takes a list of arguments supplied at the command line and searches the list for matches:

    ./spy.sh ps -t 10 -n 3

    Where ps is the string , -t is the time the program sleeps between scans and -n is the number of times the scan should occur

    Then each scan should compare its results with the last scan and place the result differences in an output file with the date of the scan and the processes:

    Date
    Started: dresden0526 ps axo

    Date #scan 2
    Ended : dresden0526 ps axo

    Date #scan 3
    <no results>

    I know I should use the sed command to append started and ended to the output, but I am confused as to how I am to create a file and compare the file created the first time in the loop to the file that is created the second time the loop runs .

  4. #4
    Just Joined! mrbruno's Avatar
    Join Date
    Jan 2013
    Location
    /MilkyWay/Sol/Earth/USA/NC/Raleigh
    Posts
    66
    Is this anything like you're looking for:

    Code:
    iterations=3
    delay=10
    
    while getopts n:t: o
    do   case "$o" in
         n)   iterations="$OPTARG";;
         t)   delay="$OPTARG";;
         [?]) echo "Usage: $0 [-n iterations] [-t delay] cmd" >&2
              exit 1;;
         esac
    done
    let 'shifter=OPTIND-1'
    shift $shifter
    
    rm -f out.last out.curr
    
    loop=1
    while test $loop -le $iterations
    do
       "$@" 2>/dev/null > out.curr
       if test $loop -gt 1
       then
          if ! diff out.last out.curr >/dev/null
          then
            date
            diff out.last out.curr
            echo
          fi
       fi
       sleep $delay
       mv out.curr out.last
       let 'loop=loop+1'
    done
    
    rm -f out.last out.curr
    I was testing with a command like: cmddiff -n 10 date '+%H:%M'

    This is very quick and dirty and is fragile because it does no checking of the parameters, etc.

  5. #5
    Just Joined!
    Join Date
    Jan 2013
    Posts
    9
    Quote Originally Posted by mrbruno View Post
    Is this anything like you're looking for:

    Code:
    iterations=3
    delay=10
    
    while getopts n:t: o
    do   case "$o" in
         n)   iterations="$OPTARG";;
         t)   delay="$OPTARG";;
         [?]) echo "Usage: $0 [-n iterations] [-t delay] cmd" >&2
              exit 1;;
         esac
    done
    let 'shifter=OPTIND-1'
    shift $shifter
    
    rm -f out.last out.curr
    
    loop=1
    while test $loop -le $iterations
    do
       "$@" 2>/dev/null > out.curr
       if test $loop -gt 1
       then
          if ! diff out.last out.curr >/dev/null
          then
            date
            diff out.last out.curr
            echo
          fi
       fi
       sleep $delay
       mv out.curr out.last
       let 'loop=loop+1'
    done
    
    rm -f out.last out.curr
    I was testing with a command like: cmddiff -n 10 date '+%H:%M'

    This is very quick and dirty and is fragile because it does no checking of the parameters, etc.
    This is really helpful. I have the code for the getopts with parameter checking. Actually let me show you my code:

    Code:
    #!/bin/bash
    trap "rm psmonitor.txt; echo Interupt encountered, exiting;  exit 1" SIGHUP SIGINT SIGTERM #trap to catch interupts , deletes output and prompts user with exit condition
    CURRENT=$(date) 
    	
    usage(){
    	echo "usage $0 -t[tseconds] -n[count]"
    } #this function will print out the correct usage when the shell is run incorrectly 
    
    COUNT=5
    TIME=1
    
    until [[ $1 == -* ]]
    do
       array+=( "$1" )
       shift
    done
    
    while getopts :t:n: option #getopts to pass arguments to the script
    do 
    	case "${option}"
    	 in 
    		t) TIME="$OPTARG";;
    		n) COUNT="$OPTARG";;
    		
    		\?) case "$OPTARG" in
    			t) echo " missing time parameter." ;;
    			n) echo " missing count parameter." ;;
    			\?) echo "Error: unknown option -$option";;  #catch all error message
    			esac
    			usage #print usage to screen
    			exit 0
    			;;
    	esac 
    done
    
    echo "DATE: $CURRENT" > spy.txt
    ps axo user,pid,comm >> spy.txt
    echo " " 
    
    echo " " > temp.txt
    grep DATE spy.txt >> temp.txt
    
    for array in ${array[@]} 
    do
        grep "$array" spy.txt | sed "s/^/Started:/">> temp.txt
    done
    
    let COUNT=COUNT-1
    
    
    while [ $COUNT -gt 0 ]; do
    	echo "DATE: $CURRENT"> spy.txt
    	
    	ps axo user,pid,comm >> spy.txt  #run command ps -e to list all process and append it to thelog file
    	
    echo " "
    	
    
    echo " " > temp1.txt
    grep DATE spy.txt >> temp1.txt
    for array in ${array[@]} 
    do
        grep "$array" spy.txt >> temp1.txt
    done
    	let COUNT=COUNT-1 #count down mechanism for loop
    	sleep $TIME  #argument to wait so many seconds between iterationso fo main loop
    done
    The first check on the output is done outside the loop becuase when the program runs the processes will always be considered as "Started"

    Now I was figuring I could use the diff command to figure out if something was ended and use sed to indicate this. I am still struggling to see how I would run the command to check if something was started using the diff command.

    I am applying some of your insights to my code and will tinker with it some more. Maybe having access to all the code I was working on, you may catch something that I have missed.

  6. #6
    Just Joined!
    Join Date
    Jan 2013
    Posts
    9
    So I worked on my code a little bit and came up with some solutions.

    I used diff last.txt current.txt |sed "s/^/Ended:/" >>out.txt to output if something has ended

    Now I need to figure out how I can manipulate it to see if a new process has started

    Any ideas?

  7. #7
    Linux Newbie
    Join Date
    Nov 2012
    Posts
    224
    I feel like temporary files are useless, if you need to store data, you know arrays are useful.

    Try this (it'll simplify the parsing):

    put into the array any task you want to monitor
    Code:
    array=( apache2 getty )
    Code:
    ps $(printf -- '-C %s ' "${array[@]}") -o user=,pid=,comm=
    or if you wish ps to print tasks following the array's order
    Code:
    for i in "${array[@]}"; do ps -C "$i" -o user=,pid=,comm=
    nb: `for array in ${array[@]}` will replace the first element of the array with the last one, because $array is equal to ${array[0]}

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •