Bash script to download from google images - bash

Some weeks ago I found in this site a very useful bash script that downloads images from google image results (download images from google with command line)
Although the script is quite complicate for me, I did some simple modifications so as not to rename the results so as to keep the original names.
However, since the last week, the script stopped working... probably Google updated the code or something, and the regexes of the script don't parse the results any more. I don't know enough about google's codes, web programing or regexing to see what is wrong, although I did some educated guesses, but still didn't work.
My (unworking) tweaked script is this
#! /bin/bash
# function to create all dirs til file can be made
function mkdirs {
file="$1"
dir="/"
# convert to full path
if [ "${file##/*}" ]; then
file="${PWD}/${file}"
fi
# dir name of following dir
next="${file#/}"
# while not filename
while [ "${next//[^\/]/}" ]; do
# create dir if doesn't exist
[ -d "${dir}" ] || mkdir "${dir}"
dir="${dir}/${next%%/*}"
next="${next#*/}"
done
# last directory to make
[ -d "${dir}" ] || mkdir "${dir}"
}
# get optional 'o' flag, this will open the image after download
getopts 'o' option
[[ $option = 'o' ]] && shift
# parse arguments
count=${1}
shift
query="$#"
[ -z "$query" ] && exit 1 # insufficient arguments
# set user agent, customize this by visiting http://whatsmyuseragent.com/
useragent='Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0'
# construct google link
link="www.google.cz/search?q=${query}\&tbm=isch"
# fetch link for download
imagelink=$(wget -e robots=off --user-agent "$useragent" -qO - "$link" | sed 's/</\n</g' | grep '<a href.*\(png\|jpg\|jpeg\)' | sed 's/.*imgurl=\([^&]*\)\&.*/\1/' | head -n $count | tail -n1)
imagelink="${imagelink%\%*}"
# get file extention (.png, .jpg, .jpeg)
ext=$(echo $imagelink | sed "s/.*\(\.[^\.]*\)$/\1/")
# set default save location and file name change this!!
dir="$PWD"
file="google image"
# get optional second argument, which defines the file name or dir
if [[ $# -eq 2 ]]; then
if [ -d "$2" ]; then
dir="$2"
else
file="${2}"
mkdirs "${dir}"
dir=""
fi
fi
# construct image link: add 'echo "${google_image}"'
# after this line for debug output
google_image="${dir}/${file}"
# construct name, append number if file exists
if [[ -e "${google_image}${ext}" ]] ; then
i=0
while [[ -e "${google_image}(${i})${ext}" ]] ; do
((i++))
done
google_image="${google_image}(${i})${ext}"
else
google_image="${google_image}${ext}"
fi
# get actual picture and store in google_image.$ext
wget --max-redirect 0 -q "${imagelink}"
# if 'o' flag supplied: open image
[[ $option = "o" ]] && gnome-open "${google_image}"
# successful execution, exit code 0
exit 0

one way to invetigate : provide -x option to bash so to have the trace of your script; that is change /bin/bash to /bin/bash -x in your script -or- simply invoke your script with
bash -x <yourscript>
You can also annotate your script with echo commands to track some variables.

Related

How can I invoke another program's bash completion handler for a single subcommand of my program?

Context
I have an arduino-cli wrapper script named ino that reads target/build configuration from:
JSON files located in the sketch directory
Command-line flags/arguments
It then constructs and exec's the corresponding arduino-cli command-line.
Problem
As a convenience wrapper script, ino isn't intended to support every feature of arduino-cli. So for those tasks that ino doesn't automate, the user can instead invoke arduino-cli indirectly using the cli subcommand of ino.
For example, if the user types the following commands:
% ino cli update
% ino cli core list --all
The ino script will take everything following cli and simply append them to the arduino-cli executable. So they would be equivalent to the following commands:
% arduino-cli update
% arduino-cli core list --all
Since arduino-cli has nice bash completion for all of its subcommands and flags, I would like to hijack the same completion functionality for my ino cli subcommand.
What I've tried
The accepted answers here:
How do I autocomplete nested, multi-level subcommands?
Multi Level Bash Completion
These helped me understand how to identify the current subcommand and discriminate the completion results based upon it.
However, I couldn't figure out how to then invoke the arduino-cli completion handler using the remaining args.
Completion handler derived from accepted answer here:
How do I get bash completion for command aliases?
See my ino completion handler based on that answer below (Reference 1).
This question/answer isn't quite the same, because they can basically just install a completion handler on their alias. I'm needing to "install" one on an argument to a command/alias.
This almost seems to work. Try it with xtrace option enabled (set -x), and you can see the arduino-cli command-line is appearing in the args ... but following ino at position $0.
E.g., given ino cli core list --all to the wrapper handler, the arduino-cli handler receives ino arduino-cli core list --all. Not sure how to get rid of $0!
Reference
ino completion wrapper derived from alias-based wrappers
joinstr() {
local d=${1-} f=${2-}
shift 2 && printf %s "$f" "${#/#/$d}"
}
complete-subcmd() {
[[ ${#} -gt 2 ]] || {
printf "usage:\n\tcomplete-subcmd src-command... -- comp-func dst-command...\n"
return 1
}
# parse the command-line by splitting it into two command-lines
# of variable length, src-command and dst-command:
# 1. src-command is the trigger that invokes the real completion
# handler, comp-func.
# 2. dst-command is the leading args of the command-line passed
# to the real completion handler, comp-func, to produce the
# resulting completion choices.
unset -v dstparse
local -a srccmd dstcmd
local func
while [[ ${#} -gt 0 ]]; do
case "${1}" in
--)
# when we reach the delimiter, also shift in comp-func as
# the next argument (the real completion handler).
dstparse=1
shift
func=${1:-}
;;
*)
# if we aren't processing the delimiter, then all other
# args are appended to either src-command or dst-command.
if [[ -z ${dstparse} ]]; then
srccmd+=( "${1}" )
else
dstcmd+=( "${1}" )
fi
;;
esac
shift
done
# if the completer is dynamic and not yet loaded, try to load it
# automatically using the given command
if [[ $( type -t "${func}" ) != function ]]; then
type -p _completion_loader &> /dev/null &&
_completion_loader "${dstcmd[#]}"
fi
local wrap=$( joinstr _ "${srccmd[#]}" | tr -d -c '[A-Za-z_]' )
# replace our args with dst-command followed by whatever remains
# from the invoking command-line.
eval "
function _${wrap} {
(( COMP_CWORD+=$(( ${#dstcmd[#]} )) ))
COMP_WORDS=( "${dstcmd[#]}" \${COMP_WORDS[#]:1} )
"${func}"
return 0
}
"
# install this wrapper handler on the first word in src-command
complete -F "_${wrap}" "${srccmd[0]}"
}
complete-subcmd ino cli -- __start_arduino-cli arduino-cli
completion.bash from arduino-cli
# bash completion V2 for arduino-cli -*- shell-script -*-
__arduino-cli_debug()
{
if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
fi
}
# Macs have bash3 for which the bash-completion package doesn't include
# _init_completion. This is a minimal version of that function.
__arduino-cli_init_completion()
{
COMPREPLY=()
_get_comp_words_by_ref "$#" cur prev words cword
}
# This function calls the arduino-cli program to obtain the completion
# results and the directive. It fills the 'out' and 'directive' vars.
__arduino-cli_get_completion_results() {
local requestComp lastParam lastChar args
# Prepare the command to request completions for the program.
# Calling ${words[0]} instead of directly arduino-cli allows to handle aliases
args=("${words[#]:1}")
requestComp="${words[0]} __completeNoDesc ${args[*]}"
lastParam=${words[$((${#words[#]}-1))]}
lastChar=${lastParam:$((${#lastParam}-1)):1}
__arduino-cli_debug "lastParam ${lastParam}, lastChar ${lastChar}"
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
# If the last parameter is complete (there is a space following it)
# We add an extra empty parameter so we can indicate this to the go method.
__arduino-cli_debug "Adding extra empty parameter"
requestComp="${requestComp} ''"
fi
# When completing a flag with an = (e.g., arduino-cli -n=<TAB>)
# bash focuses on the part after the =, so we need to remove
# the flag part from $cur
if [[ "${cur}" == -*=* ]]; then
cur="${cur#*=}"
fi
__arduino-cli_debug "Calling ${requestComp}"
# Use eval to handle any environment variables and such
out=$(eval "${requestComp}" 2>/dev/null)
# Extract the directive integer at the very end of the output following a colon (:)
directive=${out##*:}
# Remove the directive
out=${out%:*}
if [ "${directive}" = "${out}" ]; then
# There is not directive specified
directive=0
fi
__arduino-cli_debug "The completion directive is: ${directive}"
__arduino-cli_debug "The completions are: ${out[*]}"
}
__arduino-cli_process_completion_results() {
local shellCompDirectiveError=1
local shellCompDirectiveNoSpace=2
local shellCompDirectiveNoFileComp=4
local shellCompDirectiveFilterFileExt=8
local shellCompDirectiveFilterDirs=16
if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
# Error code. No completion.
__arduino-cli_debug "Received error from custom completion go code"
return
else
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
if [[ $(type -t compopt) = "builtin" ]]; then
__arduino-cli_debug "Activating no space"
compopt -o nospace
else
__arduino-cli_debug "No space directive not supported in this version of bash"
fi
fi
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
if [[ $(type -t compopt) = "builtin" ]]; then
__arduino-cli_debug "Activating no file completion"
compopt +o default
else
__arduino-cli_debug "No file completion directive not supported in this version of bash"
fi
fi
fi
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
# File extension filtering
local fullFilter filter filteringCmd
# Do not use quotes around the $out variable or else newline
# characters will be kept.
for filter in ${out[*]}; do
fullFilter+="$filter|"
done
filteringCmd="_filedir $fullFilter"
__arduino-cli_debug "File filtering command: $filteringCmd"
$filteringCmd
elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
# File completion for directories only
# Use printf to strip any trailing newline
local subdir
subdir=$(printf "%s" "${out[0]}")
if [ -n "$subdir" ]; then
__arduino-cli_debug "Listing directories in $subdir"
pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
else
__arduino-cli_debug "Listing directories in ."
_filedir -d
fi
else
__arduino-cli_handle_standard_completion_case
fi
__arduino-cli_handle_special_char "$cur" :
__arduino-cli_handle_special_char "$cur" =
}
__arduino-cli_handle_standard_completion_case() {
local tab comp
tab=$(printf '\t')
local longest=0
# Look for the longest completion so that we can format things nicely
while IFS='' read -r comp; do
# Strip any description before checking the length
comp=${comp%%$tab*}
# Only consider the completions that match
comp=$(compgen -W "$comp" -- "$cur")
if ((${#comp}>longest)); then
longest=${#comp}
fi
done < <(printf "%s\n" "${out[#]}")
local completions=()
while IFS='' read -r comp; do
if [ -z "$comp" ]; then
continue
fi
__arduino-cli_debug "Original comp: $comp"
comp="$(__arduino-cli_format_comp_descriptions "$comp" "$longest")"
__arduino-cli_debug "Final comp: $comp"
completions+=("$comp")
done < <(printf "%s\n" "${out[#]}")
while IFS='' read -r comp; do
COMPREPLY+=("$comp")
done < <(compgen -W "${completions[*]}" -- "$cur")
# If there is a single completion left, remove the description text
if [ ${#COMPREPLY[*]} -eq 1 ]; then
__arduino-cli_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
comp="${COMPREPLY[0]%% *}"
__arduino-cli_debug "Removed description from single completion, which is now: ${comp}"
COMPREPLY=()
COMPREPLY+=("$comp")
fi
}
__arduino-cli_handle_special_char()
{
local comp="$1"
local char=$2
if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
local word=${comp%"${comp##*${char}}"}
local idx=${#COMPREPLY[*]}
while [[ $((--idx)) -ge 0 ]]; do
COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
done
fi
}
__arduino-cli_format_comp_descriptions()
{
local tab
tab=$(printf '\t')
local comp="$1"
local longest=$2
# Properly format the description string which follows a tab character if there is one
if [[ "$comp" == *$tab* ]]; then
desc=${comp#*$tab}
comp=${comp%%$tab*}
# $COLUMNS stores the current shell width.
# Remove an extra 4 because we add 2 spaces and 2 parentheses.
maxdesclength=$(( COLUMNS - longest - 4 ))
# Make sure we can fit a description of at least 8 characters
# if we are to align the descriptions.
if [[ $maxdesclength -gt 8 ]]; then
# Add the proper number of spaces to align the descriptions
for ((i = ${#comp} ; i < longest ; i++)); do
comp+=" "
done
else
# Don't pad the descriptions so we can fit more text after the completion
maxdesclength=$(( COLUMNS - ${#comp} - 4 ))
fi
# If there is enough space for any description text,
# truncate the descriptions that are too long for the shell width
if [ $maxdesclength -gt 0 ]; then
if [ ${#desc} -gt $maxdesclength ]; then
desc=${desc:0:$(( maxdesclength - 1 ))}
desc+="…"
fi
comp+=" ($desc)"
fi
fi
# Must use printf to escape all special characters
printf "%q" "${comp}"
}
__start_arduino-cli()
{
local cur prev words cword split
COMPREPLY=()
# Call _init_completion from the bash-completion package
# to prepare the arguments properly
if declare -F _init_completion >/dev/null 2>&1; then
_init_completion -n "=:" || return
else
__arduino-cli_init_completion -n "=:" || return
fi
__arduino-cli_debug
__arduino-cli_debug "========= starting completion logic =========="
__arduino-cli_debug "cur is ${cur}, words[*] is ${words[*]}, #words[#] is ${#words[#]}, cword is $cword"
# The user could have moved the cursor backwards on the command-line.
# We need to trigger completion from the $cword location, so we need
# to truncate the command-line ($words) up to the $cword location.
words=("${words[#]:0:$cword+1}")
__arduino-cli_debug "Truncated words[*]: ${words[*]},"
local out directive
__arduino-cli_get_completion_results
__arduino-cli_process_completion_results
}
if [[ $(type -t compopt) = "builtin" ]]; then
complete -o default -F __start_arduino-cli arduino-cli
else
complete -o default -o nospace -F __start_arduino-cli arduino-cli
fi
# ex: ts=4 sw=4 et filetype=sh
UPDATE2:
After I posted this I checked your links and after seeing the accepted answer here, I was thinking I am just old and forget that I just copied this code from that link, and it wasn't me who wrote it. Even the example used there is the same, but investigating the code further, it looks I did write this and used a different approach, and maybe this will help you understand what's going on. As I mentioned at the bottom UPDATE1 section: you need to tune the COMP variables then call the original function
Original:
I wrote an 'alias wrapper' script a couple of years ago.
The idea is to use the original bash completion with aliases even with parameters.
For example:
alias apti='apt-get install'
source alias-completion-wrapper _apt_get apti apt-get install
#here _apt_get is the original completion function
Now you can use tab to complete the package name after apti just like after apt-get install
#alias-completion-wrapper
#Example: . alias-completion-wrapper _apt_get apti apt-get install
comp_function_name="$1"
ali="$2"
shift 2
x="$#"
function_name=`echo _$# |tr ' ' _`
function="
function $function_name {
_completion_loader $1
(( COMP_CWORD += $# - 1 ))
COMP_WORDS=( $# \"\${COMP_WORDS[#]:1}\")
COMP_LINE=\"\${COMP_WORDS[#]}\"
let COMP_POINT=\${COMP_POINT}-${#ali}+${#x}
$comp_function_name
return 0
}"
eval "$function"
complete -F $function_name $ali
unset function function_name ali x
To be honest, I can't remember how it works and I didn't commented the script :)
But I think you will be able to tune this for your needs.
UPDATE1:
As I investigated the code a bit, it looks like the idea is to tune the COMP variables, then call the original function :)
UPDATE3:
I had some time, so the modification you need are:
This ${COMP_WORDS[#]} contains the current command line. ${COMP_WORDS[#]:1} cuts off the first word, which is originally the alias/command. As you want to use it after a parameter you have to cut off the parameter too.
COMP_WORDS=( $# \"\${COMP_WORDS[#]:2}\")
I don't see COMP_LINE and COMP_POINT in the other solution, but as I can recall without those, it doesn't worked well in certain circumstances. So I suppose you need:
COMP_LINE=\"\${COMP_WORDS[#]:1}\"
And here ${#ali} is the length of the command. You need to replace this with the length of your command with the parameter. eg,:"xcmd prm" -> 8 (count the space too)
let COMP_POINT=\${COMP_POINT}-${#ali}+${#x}
Not sure about (( COMP_CWORD += $# - 1 )) either remove the -1 or use -2 or leave it as it is :)
After the modifications, just change the eval to echo and remove the complete -F line. And source the script as described. This way it will echo the function what you can insert into your completion script.

(Ubuntu bash script) Setting rights from a config txt

I am a beginner and trying to write a script that takes a config file (example below) and sets the rights for the users, if that user or group doesn´t exist, they get added.
For every line in the file, I am cutting out the user or the group and check if they exist.
Right now I only check for users.
#!/bin/bash
function SetRights()
{
if [[ $# -eq 1 && -f $1 ]]
then
for line in $1
do
var1=$(cut -d: -f2 $line)
var2=$(cat /etc/passwd | grep $var1 | wc -l)
if [[ $var2 -eq 0 ]]
then
sudo useradd $var1
else
setfacl -m $line
fi
done
else
echo Enter the correct path of the configuration file.
fi
}
SetRights $1
The config file looks like this:
u:TestUser:- /home/temp
g:TestGroup:rw /home/temp/testFolder
u:TestUser2:r /home/temp/1234.txt
The output:
grep: TestGroup: No such file or directory
grep: TestUser: No such file or directory
"The useradd help menu"
If you could give me a hint what I should look for in my research, I would be very grateful.
Is it possible to reset var1 and var2? Using unset didn´t work for me and I couldn´t find variables could only be set once.
It's not clear how you are looping over the contents of the file -- if $1 contains the file name, you should not be seeing the errors you report.
But anyway, here is a refactored version which hopefully avoids your problems.
# Avoid Bash-only syntax for function definition
SetRights() {
# Indent function body
# Properly quote "$1"
if [[ $# -eq 1 && -f "$1" ]]
then
# Read lines in file
while read -r acl file
do
# Parse out user
user=${acl#*:}
user=${user%:*}
# Avoid useless use of cat
# Anchor regex correctly
if ! grep -q "^$user:" /etc/passwd
then
# Quote user
sudo useradd "$user"
else
setfacl -m "$acl" "$file"
fi
done <"$1"
else
# Error message to stderr
echo Enter the correct path of the configuration file. >&2
# Signal failure to the caller
return 1
fi
}
# Properly quote argument
SetRights "$1"

Crontab will not execute .sh but crontab will execute a command

This issue is currently driving me nuts.
I setup a crontab with sudo crontab -e
The contents are 1 * * * * /home/bolte/bin/touchtest.sh
The contents of that file are:
#!/bin/bash
touch /home/bolte/bin/test.log
It creates the file. But the below script will not run.
#!/bin/bash
# CHANGE THESE
auth_email="11111111#live.co.uk"
auth_key="11111111111111111" # found in cloudflare
account settings
zone_name="11111.io"
record_name="11111.bolte.io"
# MAYBE CHANGE THESE
ip=$(curl -s http://ipv4.icanhazip.com)
ip_file="/home/bolte/ip.txt"
id_file="/home/bolte/cloudflare.ids"
log_file="/home/bolte/cloudflare.log"
# LOGGER
log() {
if [ "$1" ]; then
echo -e "[$(date)] - $1" >> $log_file
fi
}
# SCRIPT START
log "Check Initiated"
if [ -f $ip_file ]; then
old_ip=$(cat $ip_file)
if [ $ip == $old_ip ]; then
echo "IP has not changed."
exit 0
fi
fi
if [ -f $id_file ] && [ $(wc -l $id_file | cut -d " " -f 1) == 2 ]; then
zone_identifier=$(head -1 $id_file)
record_identifier=$(tail -1 $id_file)
else
zone_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" -H "X-Auth-E$
record_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_record$
echo "$zone_identifier" > $id_file
echo "$record_identifier" >> $id_file
fi
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_ident$
[ Read 55 lines (Warning: No write permission) ]
^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos ^Y Prev Page
^X Exit ^R Read File ^\ Replace ^U Uncut Text ^T To Linter ^_ Go To Line ^V Next Page
I've been trying to troubleshoot why this code will not run every minute, there doesn't seem to be any output in the same folder as the script, which is located at /home/bolte/cloudflare-update-record.sh
Ok so the answer to this was, I was editing crontab with sudo, and the files were located in my users home folder. This is why they weren't working. Resolved my own issue.
If you have this issue just use $ crontab -e rather than sudo crontab -e, and specify full paths for your file outputs, unless you are putting the proper path variables in your script.

Curl not downloading files correctly

So I have been struggling with this task for eternity and still don't get what went wrong. This program doesn't seem to download ANY pdfs. At the same time I checked the file that stores final links - everything stored correctly. The $PDFURL also checked, stores correct values. Any bash fans ready to help?
#!/bin/sh
#create a temporary directory where all the work will be conducted
TMPDIR=`mktemp -d /tmp/chiheisen.XXXXXXXXXX`
echo $TMPDIR
#no arguments given - error
if [ "$#" == "0" ]; then
exit 1
fi
# argument given, but wrong format
URL="$1"
#URL regex
URL_REG='(https?|ftp|file)://[-A-Za-z0-9\+&##/%?=~_|!:,.;]*[-A-Za-z0-9\+&##/%=~_|]'
if [[ ! $URL =~ $URL_REG ]]; then
exit 1
fi
# go to directory created
cd $TMPDIR
#download the html page
curl -s "$1" > htmlfile.html
#grep only links into temp.txt
cat htmlfile.html | grep -o -E 'href="([^"#]+)\.pdf"' | cut -d'"' -f2 > temp.txt
# iterate through lines in the file and try to download
# the pdf files that are there
cat temp.txt | while read PDFURL; do
#if this is an absolute URL, download the file directly
if [[ $PDFURL == *http* ]]
then
curl -s -f -O $PDFURL
err="$?"
if [ "$err" -ne 0 ]
then
echo ERROR "$(basename $PDFURL)">&2
else
echo "$(basename $PDFURL)"
fi
else
#update url - it is always relative to the first parameter in script
PDFURLU="$1""/""$(basename $PDFURL)"
curl -s -f -O $PDFURLU
err="$?"
if [ "$err" -ne 0 ]
then
echo ERROR "$(basename $PDFURLU)">&2
else
echo "$(basename $PDFURLU)"
fi
fi
done
#delete the files
rm htmlfile.html
rm temp.txt
P.S. Another minor problem I have just spotted. Maybe the problem is with the if in regex? I pretty much would like to see something like that there:
if [[ $PDFURL =~ (https?|ftp|file):// ]]
but this doesn't work. I don't have unwanted parentheses there, so why?
P.P.S. I also ran this script on URLs beginning with http, and the program gave the desired output. However, it still doesn't pass the test.

bash shell script to run imgcmp on two JPGs and store 'different' ones

I've got an IP camera that ftps files to a directory on my SuSE server.
I'm trying to write a shell script to do the following:
for every file in a directory;
use image compare to check this file against the next one
store the output in a file or variable.
if the next file is different then
copy the original to another folder
else
delete the original
end for
Running the following at the prompt generates this:
myserver:/uploads # imgcmp -f img_01.jpg -F img_02.jpg -m rmse > value.txt
myserver:/uploads # cat value.txt
5.559730
5.276747
6.256132
myserver:/uploads #
I know there's loads wrong with the code, the main issue I've got is with executing imgcmp from the script and extracting a value from it, so please point out the obvious as it may not be to me.
FILES=/uploads/img*
declare -i value
declare -i result
value = 10
shopt -s nullglob
# no idea what the above even does #
# IFS=.
# attempt to read the floating point number from imgcmp & make it an integer
for f in $FILES
do
echo "doing stuff w/ $f"
imgcmp -f 4f -F 4f+1 -m rmse > value.txt
# doesn't seem to find the files from the variables #
result= ( $(<value.txt) )
if [ $result > $value ] ; then
echo 'different';
# and copy it off to another directory #
else
echo 'same'
# and delete it #
fi
if $f+1 = null; then
break;
fi
done
when running the above, I get an error cannot open /uploads/img_023.jpg+1
and doing a cat of value.txt shows nothing, so all the files show as being the same.
I know where the issues are, but I've got no idea what I should actually be doing to extract the output of imgcmp (run from within a script) and then get it into a variable that I can compare it with.
FILES=/uploads/*
current=
for f in $FILES; do
if [ -z "$current" ]; then
current="$f"
continue
fi
next="$f"
echo "<> Comparing $current against $next"
## imgcmp will return non-0 if images cannot be compared
## and print an explanation message to stderr;
if result=$(imgcmp -f $current -F $next -m rmse); then
echo "comparison result: " $result
## Checking whether the first value returned
## is greater than 10
if [ "$(echo "$result" | awk '$1 > 10 {print "different"}')" = "different" ]; then
echo 'different';
# cp -v $current /some/other/folder/
else
echo 'same'
# rm -v $current
fi
else
## images cannot be compared... different dimensions / components / ...
echo 'wholly different'
# cp -v $current /some/other/folder/
fi
current="$next"
done

Resources