This question already has an answer here:
Bash String Comparison sha256sum
(1 answer)
Closed 27 days ago.
This post was edited and submitted for review 26 days ago and failed to reopen the post:
Original close reason(s) were not resolved
I know that you can use shasum -a 256 filename to create a SHA-256 checksum for a file, but how can one automate the check if known SHA-256 matches a file on a mac?
Since the Mac shell is zsh by default, but our CI runner uses bash, I want to know both versions (for local testing and for the ci).
I figured it out!
Using the awk '{ print $1 }', you can omit the filename printed by shasum. This way you can write an easy if statement to check if the SHA checksums match.
zsh version
sha=$( shasum -a 256 filename | awk '{ print $1 }')
if [[ $sha == "known checksum" ]] {
echo "sha matches"
} else {
echo $sha "does not match the required: known checksum"
}
bash version
sha=$( shasum -a 256 filename | awk '{ print $1 }')
if [[ $sha == "known checksum" ]]
then
echo "sha matches"
else
echo $sha "does not match the required: known checksum"
fi
Related
This question already has answers here:
"echo -n" prints "-n"
(11 answers)
Closed 3 years ago.
I have the following bash script and seems the -n flag is always interpreted as string in echo
echo Hello, who am I talking to?
read login_name
login_name=$(echo -n $login_name | base64)
echo $login_name | base64 --decode
How do i correct that, or is there any other better syntax for my script?
Better use more portable printf instead of echo -n and use read -p with correct quoting;
read -p 'Hello, who am I talking to? ' login_name
login_name=$(printf '%s' "$login_name" | base64)
printf '%s' "$login_name" | base64 --decode
echo
PS: Just to clarify that there is nothing special about using any flag inside $(...) so one can use it like this:
dt=$(date -u '+%Y/%m/%d')
echo "$dt"
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.
I posted earlier with something similar to this. I am trying to check if a user is online with the command $ ./user mburkhar which prints out mburkhar is logged on. My program works correctly but if I just type $ ./user mb is also states mb is logged on. What I have is fine, but is there a way to match what the user typed in exactly instead of slightly matching the first 2 characters..?
Here is my program so you can see what I did:
# Check if a user is logged on
if [ -z $1 ] ; then
read user
else
user=$1
fi
if [ `who | cut -d" " -f1 | grep $1` ] ; then
echo "$1 is logged on"
else
echo "$1 is either not valid or logged on"
fi
To complement the accepted answer:
-w works well and is widely supported (GNU Grep, BSD Grep), but it is not POSIX-compliant.
In your case, given that your output lines contain just a username each and nothing else, using -x - to match entire lines - would make sense too (and it is POSIX-compliant).
Also, since you're searching for a literal username, it's good practice to use grep's -F option to indicate just that.
Using [ $(...) ] (or [ `...` ]) to test for nonempty output from a command is somewhat fragile and inefficient; it's better and simpler to:
use commands directly
base the test on the exit code
and suppress stdout output, if needed
grep's -q option not only suppresses stdout, but also makes the search potentially more efficient by terminating once the first match is found (with exit code 0 to indicate success):
if who | cut -d' ' -f1 | grep -Fxq "$1"; then # ...
Similarly, [ -z $1 ] is fragile in that would break if an argument with embedded whitespace is passed - not likely in this case, but it's better to get in the habit of using [[ -z $1 ]] (or, if you must remain POSIX-compliant, [ -z "$1" ]).
Outside of [[ ... ]], it makes sense to habitually double-quote variable references, such as the $1 in the grep command.
If we put it all together:
# Check if a user is logged on
if [[ -z $1 ]]; then
read user
else
user=$1
fi
if who | cut -d' ' -f1 | grep -Fxq "$1"; then
echo "$1 is logged on"
else
echo "$1 is either not valid or logged on"
fi
You can use grep's -w (--word-regexp) option to match only entire words. Replacing grep $1 with grep -w $1 in your script should fix it.
Specify the start and end of string anchors like this:
if [ -z $1 ] ; then
read user
else
user="^$1$"
fi
if [ $(who | cut -d" " -f1 | grep $user | uniq ) ] ; then
echo "$1 is logged on"
else
echo "$1 is either not valid or logged on"
fi
I also added the uniq to remove duplicate matches, in case an user got more than one tty, or [ will exit with: [: too many arguments
The command:
value=${value%?}
will remove the last character from a variable.
Is there any logical reason why it would not work from within a script?
In my script it has no effect whatsoever.
if [[ $line =~ "What I want" ]]
then
if [[ $CURRENT -eq 3 ]]
then
echo "line is " $line
value=`echo "$line" | awk '{print $4}'`
echo "value = "$value
value=${value%?}
echo "value = $value "
break
fi
fi
I cant post the whole script, but this is the piece I refer to. The loop is being entered properly, but the 2 echo $value lines return the same thing.
Edit - this question still stands. The code works fine line bu line in a terminal, but all together in a script it fails.
Echo adds an extra line character to $value in this line:
value=`echo "$line" | awk '{print $4}'`
And afaik that extra char is removed with %?, so it seems it does not change anything at all.
Try echo -n instead, which does not add \n to the string:
value=`echo -n "$line" | awk '{print $4}'`
Since you have provided only the relevant part in the code and not the whole file, I'm going to assume that the first line of your file reads `#!/bin/sh'. This is your problem. What you are trying to do (parameter expansion) is specific to bash, so unless /bin/sh points to bash via a symlink, then you are running the script in a shell which does not understand bash parameter expansion.
To see what /bin/sh really is you can do: ls -l /bin/sh. And to remedy the situation, force the script to run in bash by changing the `shebang' at the top to read `#!/bin/bash'
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Unix for loop help please?
I am trying to list the names of all the files in a directory separated by a blank line. I was using a for loop but after trying a few examples, none really work by adding blank lines in between. Any ideas?
Is there any command which outputs only the first line of a file in unix? How could I only display the first line?
for i in ls
do
echo "\n" && ls -l
done
for i in ls
do
echo "\n"
ls
done
Use head or sed 1q to display only the first line of a file. But in this case, if I'm understanding you correctly, you want to capture and modify the output of ls.
ls -l | while read f; do
printf '%s\n\n' "$f"
# alternately
echo "$f"; echo
done
IFS="
"
for i in $(ls /dir/name/here/or/not)
do
echo -e "$i\n"
done
To see the first part of a file use head and for the end of a file use tail (of course). The command head -n 1 filename will display the first line. Use man head to get more options. (I know how that sounds).
Use shell expansion instead of ls to list files.
for file in *
do
echo "$file"
echo
if [ -f "$file" ];then
read firstline < "$file"
echo "$firstline" # read first line
fi
done