#!/bin/sh
for arg1 in "$@"
do
counter=0
for arg2 in "$@"
do
if [ "$arg2" = "$arg1" ] && [ $counter -eq 0 ]
then
counter=$((counter+1))
continue
fi
if [ "$arg2" = "$arg1" ]
then
echo
echo "Error: Two or more arguments are the same."
echo
echo "Exiting..."
echo
exit 1
fi
done
done
exit 0
#!/bin/sh
for arg1 in "$@"
do
counter=0
for arg2 in "$@"
do
if [ $counter -eq 0 ]
then
counter=$((counter+1))
continue
fi
if [ "$arg2" = "$arg1" ]
then
echo
echo "Error: Two or more arguments are the same."
echo
echo "Exiting..."
echo
exit 1
fi
done
done
exit 0
It outpouts:
[john@manjaromatepc Downloads]$ ./script.sh ~/Documents/ ~/Downloads/
Error: Two or more arguments are the same.
Exiting...
[john@manjaromatepc Downloads]$
Since both of your scripts are comparing every element of the operand list to every element of the operand list, one might expect that there would be at least two cases where the operands would be identical. Those cases would be when you're comparing the first operand to the first operand (i.e., $HOME/Documents/ to $HOME/Documents/ ) and when you're comparing the second operand to the second operand (i.e., $HOME/Downloads/ to $HOME/Downloads/ ).
Maybe there is a logical mistake in both scripts???
What is the logic in both of your scripts behind the variable named counter ? Why does it matter what the value of $counter is when trying to determine whether or not two command-line arguments are the same?
There doesn't appear to be any attempt to keep from checking one element against itself in your command-line argument vector in either of your shell scripts.
I repeat: "What is the logic in both of your scripts behind the variable named counter ? Why does it matter what the value of $counter is when trying to determine whether or not two command-line arguments are the same?"
When the shell script starts, both arg1 and arg2 have the same value.
So I use the counter with value 0, to determine this case, and advance the second for-loop to the next argument, and from there, I check if arg2=arg1.
If the second loop ends, the first loop progresses to the next argument.
The second loop restarts again with the first argument, and proceeds until it meets the first loop, where arg2=arg1 and counter -eq 0.
arg2 then proceeds to the next argument, until it ends, if no duplicate arguments found.
Then the first loop progresses to the next argument. etc.
The code that works, is the first I posted, and is this:
#!/bin/sh
for arg1 in "$@"
do
counter=0
for arg2 in "$@"
do
if [ "$arg2" = "$arg1" ] && [ $counter -eq 0 ]
then
counter=$((counter+1))
continue
fi
if [ "$arg2" = "$arg1" ]
then
echo
echo "Error: Two or more arguments are the same."
echo
echo "Exiting..."
echo
exit 1
fi
done
done
exit 0
I generally avoid eval , but have you considered making your shell script more like your C++ code?
#!/bin/sh
#set -xv
i=1
while [ $i -le $# ]
do j=$((i + 1))
while [ $j -le $# ]
do if eval [ \"\${$i}\" = \"\${$j}\" ]
then printf '\n%s (%d,%d)\n\nExiting...\n\n' \
'Error: Two or more arguments are the same:' \
$i $j >&2
exit 1
fi
j=$((j + 1))
done
i=$((i + 1))
done
The while loops in the above script could be simplified to for loops that are accepted by many shells (including recent versions of bash and ksh ) but they are extensions to the standards and, therefore, not available in several shells. The above code just uses standard utility interfaces and shell language constructs. For shells that accept these extensions, the below code looks even more like your C++ code.
#!/bin/sh
set -xv
for ((i = 1; i <= $#; i++))
do for ((j = i + 1; j <= $#; j++))
do if eval [ \"\${$i}\" = \"\${$j}\" ]
then printf '\n%s (%d,%d)\n\nExiting...\n\n' \
"Error: Two or more arguments are the same:" \
$i $j >&2
exit 1
fi
done
done
Note that both of these script write their error messages to the standard error output instead of to standard output and both of these script print the argument numbers of the first found pair of identical argument in their diagnostics.