Compare variables [closed] - bash

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I have a date in file called lastbackup with date in the yyyymmdd format. Now, I would like to compare this string with current date in the same format in BASH.
I have:
#!/bin/bash
cd ~
DATE=`date +%Y%m%d`
LASTBACKUP=sudo cat ./lastbackup
echo $LASTBACKUP
echo $DATE
if [ "$LASTBACKUP" == "$DATE" ]; then
echo "Do nothing, already processed."
else
echo "Do something, not processed"
echo -n $DATE > ./lastbackup
fi
I keep getting Do something... and I can't figure out why DATE and LASTBACKUP variables are different, because in output it looks like they are equal:
$ testeq
20140407
20140407
Do something, not processed
When I use (as suggested by Alex):
echo "LASTBACKUP: '$LASTBACKUP'"
echo "DATE: '$DATE'"
Then I get:
$ testeq
20140407LASTBACKUP: ''
DATE: '20140407'
And now it is clear to me what is going on.

Here's the reason this is wrong:
LASTBACKUP=sudo cat ./lastbackup
When you execute a command in this form:
var=val var2=val2 ... command arg arg ...
The variables are put into the environment of the command, and only into that environment. So, while cat is running, it has an environment variable named LASTBACKUP with the value "sudo". Once cat is finished, that variable will disappear.
The contents of the ./lastbackup file get cat'ed to stdout. I'm surprised you don't see a blank line when you echo $LASTBACKUP. Check your files for CRLF line endings, or perhaps the ./lastbackup file does not end with a newline.
When you're debugging and printing variables out, do something more obvious to see their value:
printf "LASTBACKUP='%s'\n" "$LASTBACKUP"
# or
for var in DATE LASTBACKUP; do
printf "%s='%s'\n" "$var" "${!var}"
done
bash has a builtin way to read a file so you don't have to call cat: this will have you a couple of milliseconds:
lastbackup=$(< ./lastbackup)
Get out of the habit of using ALL_CAPS_VARS -- one day you'll use PATH=something and then wonder why your script stops working.

Yep, the problem is probably that you're not actually initializing the LASTBACKUP variable anywhere.
But the fact that you're trying to read it with sudo bothers me. Doesn't the user that runs the script has permission to read a file that is in its $HOME? You are cd'ing into ~, which is the user's home, but since you're sudoing its read makes me think that maybe that file is in /root/lastbackup? Why would you sudo its reading otherwise?
This should do the trick:
#!/bin/bash
# For testings:
# date +%Y%m%d > $HOME/lastbackup # Uncomment to create a "./lastbackup" test file.
# Let's beging
cd ~
DATE=`date +%Y%m%d`
LASTBACKUP=`cat ./lastbackup`
echo $LASTBACKUP
echo $DATE
if [ "$LASTBACKUP" == "$DATE" ]; then
echo "Do nothing, already processed."
else
echo "Do something, not processed"
echo -n $DATE > ./lastbackup
fi
Another option, if you're running a fairly new version of bash, and since your date format doesn't have any non-number character as separator (no - , / ...) would be consider the values numbers in the if:
if (( $LASTBACKUP == $DATE )); then
echo "Do nothing, already processed."
else
echo "Do something, not processed"
echo -n $DATE > ./lastbackup
fi
And, while testing, don't escape the LASTBACKUP or DATE variables with quotation marks ". If there was a problem reading the file (or getting the current date, but I doubt that one) you'll see an error. It'll help debugging.

Related

Bash Script to update file progrmatically [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a file with contents like this
adv_dir=2
ami_pro=3
I have a variable $TEMP with value ami_pro, I want to increase the value of $TEMP by 1.
Want a bash script for this.
State of file after updates
adv_dir=2
ami_pro=4
Icky-ish, spooky indirection, but...
$: echo $TEMP
ami_pro
$: echo $ami_pro
4
$: (($TEMP++)) # $TEMP evals to ami_pro, which gets incremented
$: echo $TEMP
ami_pro
$: echo $ami_pro
5
$: let $TEMP++ # same, likely in any arithmetic context
$: echo $ami_pro
6
so...
TEMP=ami_pro # just setting in the env
grep "$TEMP=" file > $TEMP.tmp # grap the line we need to edit
. $TEMP.tmp # souce it to set the var
sed -i "s/$TEMP=${!TEMP}/$TEMP=$((++$TEMP))/" file # in-place edit
You could skip the tempfile with eval "$(grep "$TEMP=" file)" but eval makes me itch.
The sed is an in-place edit of file using double-quotes to allow the OS to pre-process the vars before making the update.
TEMP=ami_pro
so
$TEMP=${!TEMP}
is parsed by the OS into
ami_pro=$ami_pro
Since we sources the line that said ami_pro=3, that gets further parsed into
ami_pro=3
then
$TEMP=$((++$TEMP))
becomes ami_pro=$((++ami_pro)) which processes to
ami_pro=4
all sed gets is the result strings, so by the time sed starts parsing, what it sees is
s/ami_pro=3/ami_pro=4/
Once that edit is handled, we can break out of the loop.
You can use awk for that:
#!/bin/bash
TMP_FILE=$(mktemp)
awk -F= "/^${TEMP}=/ {print \$1 \"=\" \$2 + 1 \"*\"; next} 1" "${1}" > ${TMP_FILE} && mv ${TMP_FILE} "${1}"
rm ${TMP_FILE}
Pass the file with the data as a parameter to this script.

Unix how to store fuser command output to a variable

I'm a newbie in scripting and I have this problem:
I want to use the fuser command to check if a file with that name is present. I want to save the output of the command and later use it to rename the file before loading.
I have tried the following:
#!/bin/bash
file_name='test'
echo 'file_name before: '$file_name
file_name=`fuser FILE_DIR/SD/Test_file_??????????????.dat`
echo 'file_name after: '$file_name'
However, the result of the above code is:
-bash-3.00$ script.sh
file_name before :test
FILE_DIR/SD/Test_file_20180823120345.dat
file_name after:
The output of the command is not getting stored in variable but getting displayed in screen and I can't figure out why!
What I want to do is to store Test_file_20180823120345.dat in the file_name variable, and then remove the timestamp from that and rename the file to Test_file_20180823.dat.
Then after loading the data in the staging table again rename the file to the old file name that we have received and then archive the file with its original name.
Your problems is a missing closing single quote in:
echo 'file_name before: '$file_name
(which is also why you had to unbalance the quotes in echo 'file_name after: '$file_name' on the last line to get the script to run)
Instead, simply double-quote the entire string for echo that will allow expansion of your variable file_name, e.g.
echo "file_name after: $file_name"
Further, avoid using backticks for command substitution, instead use the $(...) form, e.g.
file_name=$(fuser FILE_DIR/SD/Test_file_??????????????.dat)
Or re-written it could be:
#!/bin/bash
file_name='test'
echo "file_name before: $file_name"
file_name=$(fuser FILE_DIR/SD/Test_file_??????????????.dat)
echo "file_name after: $file_name"
(note: your matching with fuser will only match a pattern with 14 characters after Test_file_ followed by .dat -- which may be what you want, but it can probably be written in a cleaner way depending on the possibilities of ??????????????)
While fuser will provide an error, you may also want to get in the habit of validating that your command substitution returned a variable by testing whether file_name is empty after the call to fuser, e.g.
#!/bin/bash
file_name='test'
echo "file_name before: $file_name"
file_name=$(fuser FILE_DIR/SD/Test_file_??????????????.dat)
if [ -z "$file_name" ]; then
echo "error: no file matched pattern" >&2
else
echo "file_name after: $file_name"
fi
Look things over and let me know if you have further questions.

printing output of command history 1 from shell script

Here's my problem, from console if I type the below,
var=`history 1`
echo $var
I get the desired output. But when I do the same inside a shell script, it is not showing any output. Also, for other commands like pwd, ls etc, the script shows the desired output without any issue.
As value of variable contains space, add quotes around it.
E.g.:
var='history 1'
echo $var
I believe all you need is this as follows:
1- Ask user for the number till which user need to print the history in script.
2- Run the script and take Input from user and get the output as follows:
cat get_history.ksh
echo "Enter the line number of history which you want to get.."
read number
if [[ $# -eq 0 ]]
then
echo "Usage of script: get_history.ksh number_of_lines"
exit
else
history "$number"
fi
Added logic where it will check arguments if number of arguments passed is 0 then it will exit from script then.
By default history is turned off in a script, therefore you need to turn it on:
set -o history
var=$(history 1)
echo "$var"
Note the preferred use of $( ) rather than the deprecated backticks.
However, this will only look at the history of the current process, that is this shell script, so it is fairly useless.

sh shell conditionals and output ": not found:" [duplicate]

This question already has answers here:
Bash script prints "Command Not Found" on empty lines
(17 answers)
Closed 6 years ago.
I am trying to learn more shell scripting. The available shells on this machine are /bin/sh, /bin/csh, and /bin/tcsh with sh being default and used here. OS is FreeBSD 9.1-RELEASE.
My current project needs to check whether a process updated the database yesterday. The first two echoes are just there for the moment verifying the variables have what I think they do.
#!/bin/sh
lastcheck=$(mysql -h dbserver.mysite.com -u myuser -pmypass mydb -se "SELECT MAX(DATE_FORMAT(datetime_sent_to_fulfiller,'%Y%m%d')) FROM print_mailing_request;"|cut -f1)
yesterday=$(echo -e "$(TZ=GMT+30 date +%Y%m%d)\n$(TZ=GMT+20 date +%Y%m%d)" | grep -v $(date +%Y-%m-%d) | tail -1)
echo "previous day was $yesterday"
echo "we last checked on $lastcheck"
if [ "$lastcheck" -eq "$yesterday" ]; then
echo "cool"
else
echo "uncool"
fi;
One question is why the : not found: output is showing up and how do I prevent it?
Another question is why both 'cool' and 'uncool' are being echoed?
Last question is why 'else' is being echoed?
$ /bin/sh pmr.cron.sh
: not found:
previous day was 20160602
we last checked on 20160602
: not found:
: not found:
cool
: not found: else
uncool
: not found:
You have carriage returns in your script; that generates the "not found" messages and is probably why both branches of your if are getting generated.
Your dates are comparable as strings, no need to use -eq to compare them as numbers.

passing variables to a bash script

I have a bash script "test.sh" and one parameter I want to use is --no-email.
when I run test.sh --no-email, everything works as expected and I do not receive an email status report.
However what I really want to run is "test.sh test.cnf" where the --no-email parameter is stored in the test.cnf file along with a load of other parameters. I cant for the life of me get this to work. Perhaps I am being completely stupid and not understanding?
Many thanks
echo $*|grep -se '--no-email'&>/dev/null
SEND_MAIL=`echo $?`
echo -e "DEBUG: \$*=$*"
if [ ! "$SEND_MAIL" == "0" ]; then
echo 'Mail would have been sent!'
else
echo 'NO MAIL WOULD HAVE BEEN SENT!'
fi
If you cannot modify the script test.sh to support this you still can use this syntax to fetch parameters from a config file:
test.sh $(<test.cnf)
If this assumption is not true, i.e. you want to modify test.sh itself to support this then you have to be more specific about what happens inside test.sh.
Edit: Now the content of test.sh has been added to the question. Starting from there the most simple thing to do would be like this:
grep -sqe '--no-email' "$*"
SEND_MAIL=$?
But you wrote that you have a bunch of other paramaters. Doing a grep for each one might be inconvenient. In this case you can loop over the word of a cnf file like this:
#!/bin/bash
while read line; do
for word in $line; do
echo "examing $word"
case "$word" in
--no-email)
SEND_MAIL=0
;;
--no-foo)
NO_FOO=0
;;
*)
echo 1>&2 "WARNING: Unknown parameter: $word"
;;
esac
done
done < "$1"

Resources