LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   why won't if [ ! cmp -s A B ] work? (https://www.linuxquestions.org/questions/linux-software-2/why-wont-if-%5B-cmp-s-a-b-%5D-work-4175695078/)

centguy 05-13-2021 09:50 AM

why won't if [ ! cmp -s A B ] work?
 
I think in bash,
this works.

Code:

if ! cmp -s A B;
then
  echo A and B are different
fi

Strangely enough
this won't work


Code:

if [ ! cmp -s A B ]; then
then
  echo A and B are different
fi

it says too many arguments.

EdGr 05-13-2021 10:01 AM

The second example has the word "then" twice.
Ed

boughtonp 05-13-2021 10:54 AM


 
Always post the actual commands being entered and exact error messages. (i.e. copy and paste both of them.)

"[" is an alias for "test", which deals with expressions.
"if" does not deal with expressions, it deals with commands.
"!" happens to be valid syntax both before test expressions and before a command.
"cmp" is a command/executable, not an expression.


centguy 05-13-2021 11:15 AM

Sorry,

the script content is

Code:

if [ ! cmp -s A B ];
then
  echo A and B are different
fi

but the error is

Quote:


./scr: line 1: [: too many arguments


EdGr 05-13-2021 12:42 PM

The square bracket interprets its argument as an expression. The script should not put square brackets around a command.

Do "man bash" and search for "test expr".
Ed

teckk 05-13-2021 03:21 PM

Couple of examples. If this is what you are looking for.
Code:

echo "Mary had a little lamb" > A
echo "Mary had a little" > B

cmp A B
A B differ: byte 18, line 1

#######

if cmp A B | grep "differ"; then
    echo "They are different"
else
    echo "They are the same"
fi
A B differ: byte 18, line 1
They are different

if cmp A A | grep "differ"; then
    echo "They are different"
else
    echo "They are the same"
fi
They are the same

########

if [[ "$(cmp A B)" =~ "differ" ]]; then
    echo "They are different"
else
    echo "They are the same"
fi
They are different

if [[ "$(cmp A A)" =~ "differ" ]]; then
    echo "They are different"
else
    echo "They are the same"
fi
They are the same

#######

[[ "$(cmp A B)" == *"differ"* ]] && echo "Yes" || echo "No"
Yes
[[ "$(cmp A A)" == *"differ"* ]] && echo "Yes" || echo "No"
No


centguy 05-13-2021 11:42 PM

Thank you folks!

I thought cmp returns True or False but it gives a chunck of text if there is a difference.

pan64 05-14-2021 01:41 AM

The general approach is:
if <commandA>; then <commandB> else <commandC> fi
<commandA> can be anything, if will only examine its exit code. So test, [, cmp or anything which can return an exit code should work.
! will just reverse the condition, exchange the than/else parts.

Quote:

Originally Posted by centguy (Post 6250480)
I think in bash,
this works.
Code:

if ! cmp -s A B;
then
echo A and B are different
fi


This one should work if A and B are two files. Would be nice to know what was your problem with it.

Quote:

Originally Posted by centguy (Post 6250480)
Strangely enough
this won't work

Code:

if [ ! cmp -s A B ]; then
then
echo A and B are different
fi

it says too many arguments.

This is just wrong. The command [ (or test) has a well defined syntax and in general it accepts 2 or 3 arguments (excluding !). 4 arguments is just useless. The test command does not operate on exit codes, but expressions, therefore you can use the text produced by commands - that is the $(command) syntax.

Regarding
Code:

cmp A B | grep text
This will work the same way, the line will return an exit code (in this case produced by grep) and actually we don't really care about the exit code of cmp (which would be good enough). Additionally (in general) we must not rely on the text printed by cmp, that may cause strange things, but the exit code of cmp.

Quote:

Originally Posted by centguy (Post 6250626)
I thought cmp returns True or False but it gives a chunck of text if there is a difference.

That is [almost] true. cmp returns with an exit code, 0 means ok (or true) - files are the same, anything else means not ok (False) - files are different. if can handle it perfectly. You do not need to analyze the report of cmp to know the answer. see man page of cmp.

shruggy 05-14-2021 01:43 AM

cmp -s doesn't print anything, it only returns an exit code:
Quote:

An exit status of 0 means no differences were found, 1 means some differences were found, and 2 means trouble.

centguy 05-15-2021 03:40 AM

The problem is essentially solved.


A bit of a long story. I looked up internet and found this works

Code:

if cmp -s A B; then
  echo same
else
  echo diff
fi

Then I decided that I want to skip echo same but

Code:


if cmp -s A B; then
  #echo same
else
  echo diff
fi

simply won't work.

It says
Code:

./simple: line 3: syntax error near unexpected token `else'
./simple: line 3: `else

which is rather stupid.

If Fortran, this works:

Code:

if (a == b) then
else
  write(*,*) 'a is not equal to b'
endif

In C, this works too
Code:

  if( strcmp("a","b") == 0 ) {
  } else
  {
    printf("a is not equal to b\n");
  }


The trouble starts when I tried to take "the negative" of

if cmp -s A B; then


A general question. Is everybody forced to take a negative just to avoid an empty statement?

centguy 05-15-2021 03:48 AM

i think I have to learn the proper use of $?

as in


shruggy 05-15-2021 04:14 AM

Quote:

Originally Posted by centguy (Post 6250948)
A general question. Is everybody forced to take a negative just to avoid an empty statement?

Nope.
Code:

cmp -s A B || echo diff
Or, if you prefer using the if statement:
Code:

if cmp -s A B
then :
else echo diff
fi

Although taking a negative condition is easier (and IMO, more readable) in this case:
Code:

if ! cmp -s A B
then echo diff
fi

BTW, some shells (zsh, yash, busybox hush) would allow an empty then branch.

michaelk 05-15-2021 04:47 AM

Code:

if( strcmp("a","b") == 0 ) {
  } else
  {
    printf("a is not equal to b\n");
  }

With respect to c or FORTRAN bash does have some unusual syntax rules. However, being forced or silly to use a negative condition when both c and FORTAN have A!=B constructs to then use if-then-else seems just sloppy coding. However, what ever you are used to and what is more readable to you is probably more important.

shruggy has already posted the examples to make bash look similar to the code you are used to using.

centguy 05-15-2021 10:32 AM

Appreciate shruggy and michaelk and teckk comments:

I summarize the discussion so that those who wants to play with it can simply cut and paste:

Script:

Code:

echo "Mary had a little lamb" > A
echo "Mary had not a little lamb" > B

echo "Test 1"
if cmp -s A A
then :
else
  echo diff
fi

echo "Test 2"
if cmp -s A B
then :
else
  echo diff
fi

echo "Test 3"
cmp -s A A && echo same || echo diff

echo "Test 4"
cmp -s A B && echo same || echo diff

Result:

Code:

Test 1
Test 2
diff
Test 3
same
Test 4
diff


pan64 05-15-2021 01:14 PM

Quote:

Originally Posted by centguy (Post 6250948)
The problem is essentially solved.

Then I decided that I want to skip echo same but

Code:


if cmp -s A B; then
  #echo same
else
  echo diff
fi

simply won't work.

It says
Code:

./simple: line 3: syntax error near unexpected token `else'
./simple: line 3: `else

which is rather stupid.

A general question. Is everybody forced to take a negative just to avoid an empty statement?

No, it is not that stupid. You have to put something between the two keywords then and else.
It is still valid for your c example too (where you omit the then, but cannot omit the {}).


All times are GMT -5. The time now is 01:17 AM.