View Full Version : Bash script. How to set file $blah = word in a file
Vinno
November 19th, 2008, 11:38 PM
This returns: tripwire --update -r /var/lib/tripwire/report//tmp/tripwire.temp.update
I want $twupdate = the content in the 'tripwire.temp.update' file not the path.
How would I go on about doing that?
Thanks in advance.
# writes the results of 'ls -lah' to a temp file
sudo ls -lah /var/lib/tripwire/report/ > /tmp/tripwire.temp.list.dir
# prints to next temp file, the last line of the result
tail -n 1 /tmp/tripwire.temp.list.dir > /tmp/tripwire.temp.last.update
# grabbing and printing the 8th word to temp file
awk '{print $8}' /tmp/tripwire.temp.last.update > /tmp/tripwire.temp.update
twupdate=/tmp/tripwire.temp.update # <----- help me here
# doing the last update with the latest check file
echo "tripwire --update -r /var/lib/tripwire/report/$twupdate"
Cracauer
November 19th, 2008, 11:42 PM
This returns: tripwire --update -r /var/lib/tripwire/report//tmp/tripwire.temp.update
I want $twupdate = the content in the 'tripwire.temp.update' file not the path.
How would I go on about doing that?
Thanks in advance.
# writes the results of 'ls -lah' to a temp file
sudo ls -lah /var/lib/tripwire/report/ > /tmp/tripwire.temp.list.dir
# prints to next temp file, the last line of the result
tail -n 1 /tmp/tripwire.temp.list.dir > /tmp/tripwire.temp.last.update
# grabbing and printing the 8th word to temp file
awk '{print $8}' /tmp/tripwire.temp.last.update > /tmp/tripwire.temp.update
twupdate=/tmp/tripwire.temp.update # <----- help me here
# doing the last update with the latest check file
echo "tripwire --update -r /var/lib/tripwire/report/$twupdate"
Untested:
set -- `ls -lah /var/lib/tripwire/report/ | tail -1`
twupdate="$8"
ghostdog74
November 20th, 2008, 01:22 AM
This returns: tripwire --update -r /var/lib/tripwire/report//tmp/tripwire.temp.update
I want $twupdate = the content in the 'tripwire.temp.update' file not the path.
How would I go on about doing that?
Thanks in advance.
# writes the results of 'ls -lah' to a temp file
sudo ls -lah /var/lib/tripwire/report/ > /tmp/tripwire.temp.list.dir
# prints to next temp file, the last line of the result
tail -n 1 /tmp/tripwire.temp.list.dir > /tmp/tripwire.temp.last.update
# grabbing and printing the 8th word to temp file
awk '{print $8}' /tmp/tripwire.temp.last.update > /tmp/tripwire.temp.update
twupdate=/tmp/tripwire.temp.update # <----- help me here
# doing the last update with the latest check file
echo "tripwire --update -r /var/lib/tripwire/report/$twupdate"
twupdate=$(ls -ltr |awk 'END{print $8}')
Cracauer
November 20th, 2008, 03:27 AM
The performance is interesting.
Splitting the fields with `set --` and using tail is almost identical to using awk END.
foo1 ()
{
set -- `ls -ltr /etc/ | tail -1`
twupdate="$8"
}
foo2 ()
{
twupdate=$(ls -ltr /etc/ | awk 'END {print $8}')
}
for i in `shellsupport -c $2` ; do
$1
done
echo $twupdate
~(wavehh)50% ctime sh ~/l.sh foo1 100
09:08
0:00.66 0.66 real 0.21 user 0.48 sys 104% CPU 0/92638 faults
~(wavehh)51% ctime sh ~/l.sh foo2 100
09:08
0:00.70 0.70 real 0.24 user 0.49 sys 104% CPU 0/100109 faults
Just for fun, optimizing it more.
I thought this would be faster as it avoids forking and execing either tail or awk
foo3 ()
{
twupdate=`ls -ltr /etc | (
while read line ; do oldline=$line ; done
set -- $oldline
echo $8
)`
}
But alas:
~(wavehh)61% ctime sh ~/l.sh foo3 100
09:08
0:02.47 2.47 real 0.57 user 1.88 sys 99% CPU 0/85578 faults
That thing obviously hated the pipe. Using a fifio is only minimally better:
foo4 ()
{
rm -f /tmp/l2
mkfifo /tmp/l2 # unsafe
ls -ltr /etc/ > /tmp/l2 &
while read line ; do oldline=$line ; done < /tmp/l2
set -- $oldline
twupdate=$8
}
~(wavehh)67% ctime sh ~/l.sh foo4 100
09:08
0:02.28 2.28 real 0.62 user 1.67 sys 100% CPU 0/100671 faults
Interesting. I wouldn't have thought that the piping into a shell read loop is so bad.
You get some of the speed back by using a temporary file instead of a fifo, but not as good as the two-stage pipe.
ghostdog74
November 20th, 2008, 03:39 AM
Interesting. I wouldn't have thought that the piping into a shell read loop is so bad.
tools such as awk/grep/sed/cut etc that process files have their "while loop" compiled. Using a while loop read loop in bash is definitely slower.
Cracauer
November 20th, 2008, 03:45 AM
It's not the loop as such:
foo5 ()
{
rm -f /tmp/l2
ls -ltr /etc/ > /tmp/l2
while read line ; do oldline=$line ; done < /tmp/l2
set -- $oldline
twupdate=$8
}
~(wavehh)2% ctime sh l.sh foo5 100
21:39
0:01.06 1.06 real 0.48 user 0.56 sys 99% CPU 0/73128 faults
This is more than twice as fast as the same shell construct, but fed by a temporary file instead of a fifo.
This is surprising to me.
You can cut off a couple tens of seconds of the latter solutions by moving the "rm" and "mkfifo" out of the loop.
Cracauer
November 20th, 2008, 03:53 AM
Yeah, so bash does a lseek and an ioctl in front of every read() in that loop and reads with a blocksize of 128 bytes.
awk reads without further system calls with 4096 blocksize. Reads the whole file in 3 system calls plus one for the zero/EOF. Bash needed 1671 system calls :)
On FreeBSD /bin/sh (not bash) things are closer together.
Vinno
November 20th, 2008, 06:35 AM
Thanks for the help guys :D
I have put in a if statement but the problem now is if i accidentally just hit the 'enter' key without typing 'y' or 'n', It gives me a error.
How to kill/halt if no answer is given.
#!/bin/bash
# To check/update tripwire;
# Without having to type the command,
# remembering where tripwire reports are held
# or the last tripwire check date/time
# Asking for a check
echo -n "Want to check before update? (y/n) "
# setting $wantcheck with answer
read wantcheck
# If statements
if [ $wantcheck = y ]
then
{
# Print status to screen and do check.
echo "Doing Check"
sudo tripwire --check
}
else
{
# Print status and move on.
echo "Not doing check, moving to update."
}
fi
# getting the latest report file name
twupdate=$(sudo ls -lah /var/lib/tripwire/report/ |awk 'END{print $8}')
# Doing the tripwire database update with latest report file
sudo tripwire --update -r /var/lib/tripwire/report/$twupdate
Cracauer
November 20th, 2008, 05:38 PM
Please don't say "an error" without giving the error message ;)
That's right back to ******* where the only error message is "Didn't work!".
In any case:
if [ "$myvar" = y ] ; then
[...]
fi
You need the quotes around $myvar.
And you probably want a case statement there.
Vinno
November 20th, 2008, 06:28 PM
Thanks Cracauer :)
geirha
November 20th, 2008, 06:44 PM
You can also have read only read 1 character so you don't need to hit enter after typing y or n. And I second using case, as it is easier to check for both lower case and uppercase y.
read -n1 -p "Want to check before update? (y/n) " wantcheck
echo
case "$wantcheck" in
y|Y)
echo "yes"
;;
n|N)
echo "no"
;;
*)
echo "something else"
;;
esac
Cracauer
November 20th, 2008, 09:30 PM
"read -n" brings you from /bin/sh to bash land.
I recommend using "yepp" and "nope". Keeps users from answering too casually.
Powered by vBulletin® Version 4.2.2 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.