1

I was trying to diff some files, and do something if is different. But when combining with sh -c, diff can not return proper exit code.

root@i-qqixe8m2:~# cat /tmp/1
1
root@i-qqixe8m2:~# cat /tmp/2
2
root@i-qqixe8m2:~# set +x # Edited: useless cmd. But still kept here since answer below by @iBug would refer to this.
root@i-qqixe8m2:~# sh -c "diff /tmp/1 /tmp/2; echo $?;"
1c1
< 1
---
> 2
0
root@i-qqixe8m2:~# diff /tmp/1 /tmp/2; echo $?;
1c1
< 1
---
> 2
1
root@i-qqixe8m2:~#

PS. I found related question here: git diff and bash return code, but no reason provided, and comments below I believe is not the real right solution, since I don't use git here.

1 Answers1

2

Because you're using double quotes, $? is already expanded by your current shell instead of sh:

sh -c "diff /tmp/1 /tmp/2; echo $?;"

What sh sees is that the second command is echo 0 (the last command set +x returns 0).

To fix, use single quotes to prevent $? from being expanded by your current shell, so sh could handle it properly:

sh -c 'diff /tmp/1 /tmp/2; echo $?;'

Or maybe just escape the dollar:

sh -c "diff /tmp/1 /tmp/2; echo \$?;"

It's a good practice to debug shell commands with set -x, unsure why you did +x instead.

~ $ sh -c 'diff 1 2; echo $?;'
+ sh -c 'diff 1 2; echo $?;'
1c1
< 1
---
> 2
1
~ $ sh -c "diff 1 2; echo $?;"
+ sh -c 'diff 1 2; echo 0;'
1c1
< 1
---
> 2
0
~ $

Note the two lines starting with a +, which is what your shell has actually executed.

iBug
  • 35,554
  • 7
  • 89
  • 134