compare an image using ImageMagick and only get result true/false 0/1 - compare

We use a git repo for screenshots and always the images are marked changed by git, but with apply fuzz, there are no changes.
I use this script to compare images
do_compare()
{
compare $color_flag $fuzz_flag $backgroundcolor_flag "$f1" "$f2" png:- | \
montage -geometry +4+4 $backgroundcolor_flag "$f1" - "$f2" png:- >"$destfile" 2>/dev/null || true
}
but I want only know if there is a change in the image, with respect the fuzz, or not.
Does someone has an idea how to do so ?

You can do that in command line ImageMagick on Unix using
compare -metric ae -fuzz XX% image1 image2 null: 2>&1
-metric ae will return the number of pixels that do not match. So if the result is 0, then it matches perfectly within the specified -fuzz value.
For example, testing with fuzz = 0:
XX=0
test=`compare -metric ae -fuzz $XX% lena.png lena.jpg null: 2>&1`
if [ "$test" = "0" ]; then
echo "match"
else
echo "no match"
fi
no match
Testing with fuzz = 10%:
XX=10
test=`compare -metric ae -fuzz $XX% lena.png lena.jpg null: 2>&1`
if [ "$test" = "0" ]; then
echo "match"
else
echo "no match"
fi
match

Related

How can I get the return value of `wget` from a sh script into an `int` variable

OS: Linux raspberrypi 4.19.58-v7l+ #1245 SMP Fri Jul 12 17:31:45 BST 2019 armv7l GNU/Linux
Board: Raspberry Pi 4
I have a script:
#!/bin/bash
line=$(head -n 1 /var/www/html/configuration.txt)
file=/var/www/html/4panel/url_response.txt
if [ -f "$file" ]; then
wget_output=$(wget -q -i "$line" -O $file --timeout=2)
echo "$?"
else
echo > $file
chown pi:pi $file
fi
which I call from a C++ program using:
int val_system = 0;
val_system = system("/var/www/html/4panel/get_page.sh");
std::cout<<"System return value: "<<val_system<<std::endl;
If there is something wrong with the script, echo "$?" will output the return value of wget, but val_system will always be 0.
Does system() returns the value of echo "$?" ? In which case 0 is correct. And if that is the case how can I put the return value of wget in val_system ?
I have taken a situation in which echo "$?" always returns 8, basically I've entered an incorrect URL and:
I have tried deleting echo "$?" but val_system still returned 0;
With echo "$?" deleted I have changed the wget line to wget -q -i "$line" -O $file --timeout=2 and val_system now returns 2048.
None of my attempts bared any fruit and I have come here to seek guidance. How can I make val_system / system() return what echo "$?" returns ?
How can I get the return value of wget from the script into an int variable that's inside the C++ program that calls the script ?
The integer value system() returned contains extra information about executed command's status along with its exit code, see system() and Status Information. You need to extract exit code using WEXITSTATUS macro, like:
std::cout << "System return value: " << WEXITSTATUS(val_system) << std::endl;
If you want to echo the status and return it, you will need to save the value of $? to a variable, and exit with it explicitly.
wget_output=$(wget -q -i "$line" -O $file --timeout=2)
status=$?
...
echo $status
...
exit $status
If you don't need to execute echo or any other command between the call to wget and the end of the script, you can rely on the script exiting with the last status (i.e the one corresponding to the call to `wget) implicitly.

Bash variable substitution in a function

I have a function read_command defined as:
function read_command {
local __newline __lines __input __newstr __tmp i;
exec 3< "$*";
__newline=$'\n';
__lines=();
while IFS= read <&3 -r __line && [ "$__line" != '####' ]; do
echo "$__line";
__lines+=("$__line");
done
while IFS= read <&3 -r __line && [ "$__line" != '####' ]; do
read -e -p "${__line#*:}$PS2" __input;
local ${__line%%:*}="$__input";
done
__command="";
for i in "${__lines[#]}"; do
__tmp=$(echo "${i}");
__command="${__command} ${__newline} ${__tmp}";
done
echo -e "$__command";
}
In the current directory there is a file named "test", with the following
content:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
####
a: name of friend a
b: name of friend b
####
In the terminal, the command executed is
read_command test
With no input, I am expecting the output of the last statement to be:
greet Bob
greet Jim
But what I get is:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
What is wrong here?
Edit: As suggested by David, adding eval works in some cases except the following one.
j=1;i="export DISPLAY=:0 && Xephyr :${j}&";k=$(eval echo "$i");
echo $k
export DISPLAY=:0
I am expecting k to be "export DISPLAY=:0 && Xephyr :1&", what's wrong here?
Edit: I tried with the following
k=$(eval "echo \"$i\"")
This is the link to the script I am working on.
https://gist.github.com/QiangF/565102ba3b6123942b9bf6b897c05f87
During the first while loop, in echo "$__line", you have __line='greet ${a:-"Bob"}'. When you try to print that, Bash won't be expanding ${a:-"Bob"} into Bob. (Even if you remove the quotes around $__line this won't happen.) To get that effect, you need to add eval, as in, e.g., eval echo "$__line". Unfortunately eval comes with its can of worms, you have to start worrying about interactions between quoting levels and such.

Regex Validation Kornshell

I have the following REGEX expression
^(\(?\+?(44|0{1}|0{2}4{2})[1-9]{1}[0-9]{9}\)?)?$
In an attempt to cover all eventuality of mobile number in the UK. While parsing this validation through a REGEX tester online, which works great I am having difficulty getting it to work correctly in cornshell
fn_validate_msisdn() {
MSISDN=$1
REGEX_PTN="^(\(?\+?(44|0{1}|0{2}4{2})[1-9]{1}[0-9]{9}\)?)?$"
if [ `echo $MSISDN | egrep -c $REGEX_PTN` -gt 0 ]
then
return 1
fi
return 0;
}
Being called by:
if [ ! `fn_validate_msisdn ${MSISDN}` ]
then
...
fi
However It always seems to fail, either with illegal syntax or always returning greater than one.
some test data:
447999999999 : OK
07999999999 : OK
4407948777622 : FAIL
43743874874387439843 : FAIL
Any Suggestions would be great
Your function can be just this:
fn_validate_msisdn() {
MSISDN=$1
REGEX_PTN="^(\(?\+?(44|0{1}|0{2}4{2})[1-9]{1}[0-9]{9}\)?)?$"
echo "$MSISDN" | egrep -q "$REGEX_PTN";
}
then:
fn_validate_msisdn 43743874874387439843
echo $?
1
fn_validate_msisdn 447999999999
echo $?
0
Remember return status of 0 means success and 1 means failure here.

Find and return a specific area of a text

Hello everyone and happy new year! I have a text from which I like to return a specific area from a specific string using a python script!
This is the text I have
#!/bin/sh
case "$1" in
start)
ulimit -s 1024
/usr/bin/oscam --config-dir /etc/tuxbox/config/oscam --daemon --pidfile /tmp/oscam.pid --restart 2 --utf8
;;
stop)
kill `cat /tmp/oscam.pid` 2> /dev/null
;;
restart|reload)
$0 stop
sleep 1
$0 start
;;
version)
echo "svn8631"
;;
info)
echo "oscam svn8631"
;;
*)
echo "Usage: $0 start|stop|restart"
exit 1
;;
esac
exit 0
from the text above I need to create a python command that always returns only what is written where the oscam svn8631 is written between the quotes! So far the only thing I managed to do is return another area of this text using this code
try:
f = open("/etc/init.d/softcam", "r")
content = f.read()
f.close()
except:
content = ""
contentInfo = content.split("\n")
if (content != ""):
for line in contentInfo:
if line.__contains__("usr/bin/"):
idex = line.index("n/")
line = line[(idex + 2):]
return line
This of course returns what's after the usr/bin text, and I need another area which comes after the word info). Can anyone help me please? I don't know how to make my script read this specific area I need! Thanks in advance!
Using the content variable that you have created, the
"oscam svn8631" text can be extracted with:
for chunk in content.split(";;"):
if chunk.strip().startswith('info)'):
return chunk.split('"')[1]
The natural way to break up a bash case statement is by splitting it on ";;". Then, we identify the info section (chunk.strip().startswith('info)')) and select the first quoted string in that section (chunk.split('"')[1]).

How to separate package name by regex in bash?

I'm writing a script function to separate package tar ball name listing into package name version.
xorg-fonts-misc-1.0b-1
Xorg-font-bitstream-75dpi-1.0.0-2.i386
Xorg-font-bitstream-100dpi-1.2a-2.arm
Other-Third-Party-1.2.2-1-any
I'm using the following script to separate name and version.
split_pkgname_pipe() { # split x-x-1.3-1.x -> x-x 1.3-1.x
[ $opt_v != 0 ] && echo "dbg:split_pkgname_pipe $*" >&2
awk '{
f=$0
sub(/\-[0-9].*$/,"")
n=$1
v=substr(f, length(n)+2)
print n, v
}'
}
The problem of my code will cause Xorg-font-bitstream-75dpi-1.0.0 separate as Xorg-font-bitstream and 75dpi-1.0.0. But I want Xorg-font-bitstream-75dpi and -1.0.0
[SOLVED]
split_pkgname_pipe() { # split x-x-1.3-1.x -> x-x 1.3-1.x
[ $opt_v != 0 ] && echo "dbg:split_pkgname_pipe $*" >&2
local line namever name ver rel
while read line ; do
namever="${line%-*}"
rel="${line##*-}"
if [ `expr match $rel '[0-9]'` = 0 ] ; then # rel is 'i386/any'...
name="${namever%-*}"
ver="${namever##*-}"
namever="$name"
rel="$ver-$rel"
fi
name="${namever%-*}"
ver="${namever##*-}"
echo "$name $ver-$rel"
done
}
$ package="Xorg-font-bitstream-75dpi-1.0.0"
$ echo "${package%-*}"
Xorg-font-bitstream-75dpi
$ echo "${package##*-}"
1.0.0
Try this
sed -re '/^(.*?)((\d[a-z]?\.)+.*)$/\1\t\2/gmi' file.txt