Question: I feel I should be able to do this in my sleep, but let's say I have two text files each of which has a single column of the names of apache modules in no particular order. One file has 46 unique (to itself) strings. The other has 67 lines and 67 uniq (to the file) strings. There will be many strings in common. 

I need to find the names of apache modules that are -not- in the shorter, first file but -are- in the second, longer file. 

I want to do this by searching and comparing **strings**. Line number, order, or postition are completely irrellevant. I just want to know which modules listed only in the longer file need to be installed. 

By default uniq, comm and diff want to work by lines, and line numbers.
I don't want a side-by-side comparison; I just want a list.

Answer: 
Break your strings into lines, sort and uniqify them, and use `comm` for the analysis. (See [BashFAQ #36](http://mywiki.wooledge.org/BashFAQ/036)).

I'm going to assume, to have an example, that you want to compare the `LoadModule` directives between two Apache config files.

file1:

```
...other stuff...
LoadModule foo modules/foo.so
LoadModule bar modules/bar.so
LoadModule baz modules/baz.so
...other stuff...

```

file2:

```
...other stuff...
LoadModule foo modules/foo.so
...other stuff...

```

So, to do this:

```
comm -2 -3 \
  <(gawk '/LoadModule/ { print $2 }' file1 | sort -u)
  <(gawk '/LoadModule/ { print $2 }' file2 | sort -u)

```

...will suppress any lines found in both or only in the shorter file, and give you the module names found in the third, yielding the following output:

```
bar
baz

```

For folks looking at this question with more interesting use cases in mind -- unfortunately, while GNU sort's `-z` flag can handle NUL delimiters (to allow comparison on strings containing newlines), `comm` cannot. However, you can write your own `comm` implementation in shell which supports NUL delimiters, such as the following example:

```
#!/bin/bash
exec 3<"$1" 4<"$2"

IFS='' read -u 4 -d ''; input_two="$REPLY"

while IFS='' read -u 3 -d '' ; do
    input_one="$REPLY"
    while [[ $input_two < $input_one ]] ; do
        IFS='' read -u 4 -d '' || exit 0
        input_two="$REPLY"
    done
    if [[ $input_two = "$input_one" ]] ; then
        printf '%s\0' "$input_two"
    fi
done

```
I would run a little bash script like this (differ.bash):

```
#!/bin/bash
f1=$1; # longer file
f2=$2; # shorter file

for item in `cat $f1`
do
    match=0
    for other in `cat $f2`
    do
        if [ "$item" == "$other" ]
        then
            match=1
            break
        fi
    done
    if [ $match != 1 ]
    then
        echo $item
    fi
done

exit 0

```

Run it like so:

```
$ ./differ.bash file1 file2

```

Basically, I am just setting up a double for loop with the longer file on the outer loop and the shorter file on the inner loop. That way each item in the longer list gets compared with the items in the shorter list. This allows us to find all the items that don't match something in the smaller list.

---

**Edit:** I have tried to address Charles' first comment with this updated script:

```
#!/bin/bash
f1=$1; # longer file
f2=$2; # shorter file

while read item
do
    others=( "${others[@]}" "$item" )
done < $f2

while read item
do
    match=0
    for other in $others
    do
        if [ "$item" == "$other" ]
        then
            match=1
            break
        fi
    done
    if [ $match != 1 ]
    then
        echo $item
    fi
done < $f1

exit 0

```