Solved Bug in comm(1)?

Is this a bug in the code or a localised brain fart? In the past it's usually been the latter, but ....

Two files:

# ls -l .profile /.profile
Code:
-rw-r--r--  1 root wheel  934 May 19 09:26 .profile
-rw-r--r--  1 root wheel 1699 Jan 29  2024 /.profile

Each file contains one line beginning with PATH regardless of case:

Code:
# grep -i ^PATH .profile /.profile
.profile:PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin
/.profile:PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin

uniq(1) says those two occurrences are identical and collapses them to one:

Code:
# grep -hi ^PATH .profile /.profile | uniq
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin

comm(1) says that if lines are examined without regard to case (i.e. "loosely"), AND if lines which are in ONLY one file or the other (but not both) are suppressed, then the PATH line appears in both files:

Code:
# comm -i12 .profile /.profile
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin
export PATH
TERM=${TERM:-xterm}
export TERM
PAGER=less
export PAGER

# set ENV to a file invoked each time sh is started for interactive use.
ENV=$HOME/.shrc; export ENV

# Query terminal size; useful for serial lines.
if [ -x /usr/bin/resizewin ] ; then /usr/bin/resizewin -z ; fi

But comm(1) also says that if lines are examined including differences in case (i.e. "strictly"), then the PATH lines are in ONLY one file or the other, but not both:

Code:
# comm -12 .profile /.profile
export PATH
TERM=${TERM:-xterm}
export TERM
PAGER=less
export PAGER

# set ENV to a file invoked each time sh is started for interactive use.
ENV=$HOME/.shrc; export ENV

# Query terminal size; useful for serial lines.
if [ -x /usr/bin/resizewin ] ; then /usr/bin/resizewin -z ; fi

What's the deal? Why does comm change its tune when the -i flag is added?

# for f in .profile /.profile ; do grep ^PATH $f | hexdump -C; done
Code:
00000000  50 41 54 48 3d 2f 73 62  69 6e 3a 2f 62 69 6e 3a  |PATH=/sbin:/bin:|
00000010  2f 75 73 72 2f 73 62 69  6e 3a 2f 75 73 72 2f 62  |/usr/sbin:/usr/b|
00000020  69 6e 3a 2f 75 73 72 2f  6c 6f 63 61 6c 2f 73 62  |in:/usr/local/sb|
00000030  69 6e 3a 2f 75 73 72 2f  6c 6f 63 61 6c 2f 62 69  |in:/usr/local/bi|
00000040  6e 3a 7e 2f 62 69 6e 0a                           |n:~/bin.|
00000048
00000000  50 41 54 48 3d 2f 73 62  69 6e 3a 2f 62 69 6e 3a  |PATH=/sbin:/bin:|
00000010  2f 75 73 72 2f 73 62 69  6e 3a 2f 75 73 72 2f 62  |/usr/sbin:/usr/b|
00000020  69 6e 3a 2f 75 73 72 2f  6c 6f 63 61 6c 2f 73 62  |in:/usr/local/sb|
00000030  69 6e 3a 2f 75 73 72 2f  6c 6f 63 61 6c 2f 62 69  |in:/usr/local/bi|
00000040  6e 3a 7e 2f 62 69 6e 0a                           |n:~/bin.|
00000048
Code:
# for f in .profile /.profile ; do grep ^PATH $f | sha256sum; done
65f31ddd9ec9a472a4af87f4246a56f419ed104293cd13005e23b69a5a2a948d  -
65f31ddd9ec9a472a4af87f4246a56f419ed104293cd13005e23b69a5a2a948d  -
 
Hmm, does it have to do with:
The comm utility assumes that the files are lexically sorted

The PATH lines do appear at different line numbers:

# grep -nhi ^PATH .profile /.profile | uniq
Code:
2:PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin
5:PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:~/bin
 
Back
Top