LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Bash- file names with associated file content (http://www.linuxquestions.org/questions/programming-9/bash-file-names-with-associated-file-content-4175440175/)

towardstheedge 12-05-2012 03:16 PM

Bash- file names with associated file content
 
I am working on another optional project for my Linux class.

The basic idea is a bucket brigade. Two scripts are working together to spin off a variable number of instances of a process that hands a file from one to the next... one of the processes generates the bucket files with a random number 1 - 5 for "gallons" another interacts with the "fire" file. The rest are just handing the content of the bucket files down the line.

The part I am having trouble with is generating a report on the status of the whole thing while it is still running.

I want to be able to list the current bucket.* files that exist and the contents of them. They will each only contain a random number between 1 and 5.

It seems like there should be a tool that does this sort of thing simply but I don't know what it would be.

I got close with this:
Code:

ls | grep bucket. > .current.buckets
cat bucket.* > .bucket.contents

echo "The current active buckets and contents:"
paste .current.buckets .bucket.contents | tr '\t' '\n'

The problem with this is I can't be sure that grep and cat are listing the file name/content in the same order. I can generate an output with this which looks like what I want but I want it to be accurate.

unSpawn 12-05-2012 07:49 PM

Quote:

Originally Posted by towardstheedge (Post 4843409)
The part I am having trouble with is generating a report on the status of the whole thing while it is still running.

It would have been more interesting if you would have listed the actual scripts you used...


Quote:

Originally Posted by towardstheedge (Post 4843409)
I want to be able to list the current bucket.* files that exist and the contents of them. They will each only contain a random number between 1 and 5.

If you assert a single bucket is passed along the line (only one "bucket" file exists in the directory) then you could:
Code:

BUCKETS=0; GALLONS=0
..
if [ -f ./bucket ]; then
 ((BUCKETS++))
 CONTENT=$(cat ./bucket)
 GALLONS=$[${GALLONS}+$CONTENT]
else
 echo "Oi! Where's me bucket?"
fi

if there's multiple buckets and you have to "pass" them in numeric order (bucket.001, bucket.002)
Code:

incr() {  ((BUCKETS++)); GALLONS=$[${GALLONS}+$1]; }
find . -type f -name bucket.\*|sort -n|while read BUCKET; do
 CONTENT=$(cat ./bucket); incr $CONTENT
done

and somewhere at the end
Code:

echo "Passing ${BUCKETS} buckets containing ${GALLONS}"
*BTW unless it's a hard requirement actual bucket files shouldn't be necessary: one script, or a script consisting of several functions, could supply another script or function with bucket names and contents as arguments.

towardstheedge 12-05-2012 10:59 PM

Well I certainly can post the scripts as they are. I am new at this so they are probably not extremely clear or the best way of doing things... But I have got them running fairly well except for the one hitch. I could actually leave it off and just report the number of bucket files there are and which ones they are easily. But I wanted to add the content of each bucket file to the report.

The brig script is the primary script. The passer script is used by the brig script to instantiate passer processes.

I realize these are kinda sloppy... I didn't really start with a plan but just built in one feature at a time. There are some artefacts from testing still in there. I know the variables are a bit sloppy too. I didn't know how many I was going to use. I got a bit carried away with sending errors to /dev/null. When running the script with large numbers of passers and big fire values many processes run out of order and it really wasn't important to know about the errors when it still worked. I also wanted to make sure all the extra files were removed so I built in quite a bit of redundancy, especially with removing the buckets.

brig:
Code:

#!/bin/bash

#brig
#towardstheedge
#dec 2012

#user defines a fire
#user defines number of passers
#passers put out fire

if [[ "$2" = *[!0-9]* ]];
then
echo "The second argument may only contain digits"
exit
fi
#$2 must be empty or contain only digits
#to pass this point

case "$1" in

fire)
if [ -z "$2" ];
then
echo Please provide a fire size
echo 'exe: brig fire 10'
else
echo "$2" > .fire.size
echo "A fire of $2 intensity has started"
fi
;;

alarm)

rm .report.pas.* 2> /dev/null

if [ -z "$2" ];
then
echo Please provide the number of passers
echo 'exe: brig alarm 5'

elif [ "$2" -lt 2 ];
then
echo "There needs to be more than one passer"

else

passvar="$2"
export totalpass="$2"
#passers check exported variable to see if they
#are high number

touch .keep.passing

echo "$totalpass Passers have been activated"
while [ "$passvar" -gt 0 ];
do

bash passer "$passvar" &
((passvar--))
done
fi
;;

status)

firenow=0

clear
echo "Report of situation as of"
echo $(date)

if  [ -e .fire.size ];
then
firenow=$(cat .fire.size)
fi

if [ "$firenow" -gt 0 ];
then
echo "The fire is blazing with $firenow intensity"
else
echo "No fire is active"
fi

if [ -e .keep.passing ];
then

touch .passers.pause
sleep 3

ls | grep bucket. > .current.buckets
cat bucket.* > .bucket.contents

echo "The current active buckets and contents:"
paste .current.buckets .bucket.contents | tr '\t' '\n'

rm .current.buckets
rm .bucket.contents
rm .passers.pause

else

echo "There are no buckets currently active"

fi

;;

quit)
rm .keep.passing 2> /dev/null
sleep 1
rm .fire.size 2> /dev/null
rm bucket.* 2> /dev/null

if [ -e .report.pas.1 ];
then
cat .report.pas.* >> .unified.report
fi

clear
echo 'Generating Report for this session'
sleep 3
cat .unified.report | more
else
echo "No reports exist at this time"
fi
;;

*)
echo 'Usage: brig [fire (n)|alarm (n)|status|report|quit]'
esac


passer:
Code:

#!/bin/bash

#passer
#towardstheedge
#dec 2012

#creates the passer scripts
#used with brig script

mybuckets=0
mywater=0
#initializing variables for reporting
#keeping track of totals for each passer

case "$1" in
#case structure assigns behavior of passer instance
#3 types of passers accounted for
#passer at water - passer at fire - passers in between

$(( passnum = totalpass )) )
#if exported variable from brig = local passnum variable
#then the passer is the end of the line (high number)
#echo "Passer $passnum has arrived at the water"

while [ -e .keep.passing ];
do

if [ -e .passers.pause ];
then
sleep 1
else

  if [ ! -e bucket.$1 ];
  then
  gallons=$((RANDOM%5+1))
  echo "$gallons" > bucket.$1
  ((mybuckets++))
  mywater=$(($mywater+$gallons))
#  echo "Passer $totalpass fills a bucket with $gallons gallons"
  fi
fi
done
;;
#above is high num passer at water

1)
#echo "Passer 1 has arrived at the fire"
while [ -e .keep.passing ];
do

if [ -e .passers.pause ];
then
sleep 1
else

  if [ -e bucket.2 ];
  then
  fire1=$(cat .fire.size) 2> /dev/null
  water3=$(cat bucket.2) 2> /dev/null
  rm bucket.2
  ((mybuckets++))
  mywater=$(($mywater+$water3))
  fire2=$(($fire1-$water3))
  echo "$fire2" > .fire.size
#  echo "Passer 1 takes bucket of $water3 gallons from passer 2"
#  echo "Passer 1 dumps $water3 gallons of water on the fire"
#  echo -e  "\e[1;33mFire has been\
# reduced to a level $fire2 fire\e[00m"

        if [[ "$fire2" -le 0 && -e .keep.passing ]];
        then
        rm .keep.passing
        rm .fire.size
        echo "Fire is out"
        fi
  fi
fi
done
;;
#above is passer 1 always at fire

*)
#echo "Passer $1 is in position"

takebucket=$(($1+1))

while [ -e .keep.passing ];
do

if [ -e .passers.pause ];
then
sleep 1
else

  if [ -e bucket.$takebucket -a ! -e bucket.$1 ];
  then
  water5=$(cat bucket.$takebucket 2> /dev/null)
  rm bucket.$takebucket 2> /dev/null
  ((mybuckets++))

    if [ ! -z $water5 ];
    then
      mywater=$(($mywater+$water5)) 2> /dev/null
    fi
#strange errors occur with high values of fire/passers
#with fire size 300 and 20 passers I had several errors
#saying that $water5 contained no value
    echo "$water5" > bucket.$1
#  echo "Passer $1 takes bucket with $water5 gallons"
#  echo "from passer $takebucket"
#  sleep $1
  fi
fi
done

#above is all other passers
#not concerned with invalid $1 because
# $1 is handed to passer directly from brig
esac

rm bucket.* 2> /dev/null

echo '......................' >> .report.pas.$1
echo "For fire ending at" >> .report.pas.$1
echo $(date) >> .report.pas.$1
echo "Passer $1 handled $mybuckets buckets"\
 >> .report.pas.$1
echo "Passer $1 handled $mywater gallons of water"\
 >> .report.pas.$1
echo '......................' >> .report.pas.$1



So what I want is to be able to type "$ brig status" while the passers are still passing bucket files and have information about which buckets are active at the time and what they have in them. One or the other piece of information is easy to do but getting them to work together is what I can't figure out.

unSpawn 12-06-2012 06:36 AM

Quote:

Originally Posted by towardstheedge (Post 4843567)
So what I want is to be able to type "$ brig status" while the passers are still passing bucket files

Seeing you already have case statements to pass arguments the only thing you need to do is add a "status)" one that displays your report.

towardstheedge 12-06-2012 01:59 PM

Ya I don't know what happened. I was copy-pasting several lines at a time from nano because I don't know how to copy an entire nano file content to clipboard, I must have missed some lines... I do have a status case set up. Edit: oh wait, it is in there above the quit case below the alarm case. But it is so sloppy I couldn't even find it for a while lol. Obviously I have a lot of work to do learning to keep things a bit more organized.

Anyway, I was able to get what I wanted for my program with some help from my professor. The code that did what I want is:

Code:

for bucket in $(ls bucket.?)
do

echo -n "Bucket: $bucket contains --"
echo "$(cat $bucket) gallons"
done

... just in case someone else can use the solution sometime.


All times are GMT -5. The time now is 02:26 AM.