Question: Haven't seen a solution similar enough to this yet...

I have two files each containing a list of file names. There are overlap in the contents of the files but file A contain some file names that are not in file B. Also, the file extensions are different in files A and B. That is:

```
A                     B
------------          --------------
file-1-2.txt          file-1-2.png
file-2-3.txt          file-3-4.png
file-3-4.txt
...

```

How do I combine the two files, comma-delimited, into one ignoring lines that don't match?

That is:

```
C
------------
file-1-2.txt,file-1-2.png
file-3-4.txt,file-3-4.png

```

I believe some usage of `awk` similar to the following will work:

```
awk 'FNR==NR{NOT SURE} {print $1,$2}' fileA fileB

```

Thanks in advance!

Answer: 
This pure bash solution should work and handle dots, backslashes, dashes, and other special characters in either file.

```
mapfile -t arr_a < A
mapfile -t arr_b < B

for a in "${arr_a[@]}"; do for b in "${arr_b[@]}"; do
    [[ ${a%.*} == "${b%.*}" ]] && printf '%s,%s\n' "$a" "$b" && break
done; done

```

First, we read the contents of the files into arrays, one line per item, using `mapfile`. 1 Then, for each line in `A`, we compare to each line in `B`.

To compare only the portion before the extension, we use the shell parameter expansion `${var%pattern}`, which removes the shortest match of the glob `.*`2 from the end of the filenames.

1The -t option strips the trailing newline from the array items.

2The `.` here is literal, removing a period and everything after.
You could do:

```
$ awk 'function base(fn) {sub("[.][^.]*$", "", fn); return fn} 
       NR==FNR { fn[$1]; next} 
       {for (e in fn){ if (base(e)==base($1)){ printf "%s,%s\n", e, $1 }}} ' f1 f2
file-1-2.txt,file-1-2.png
file-3-4.txt,file-3-4.png

```

Since `awk` associative arrays are unordered, the order of the printout is determined by the order of the second file -- not the first. 

---

Explanation:

1. `function base(fn) {sub("[.][^.]*$", "", fn); return fn}` is a function that strips the extension from the filename (assuming that the extension is the non `.` characters to the right of the last `.` found. The entire name is returned if no `.` is found.)
2. `NR==FNR { fn[$1]; next}` read each line (each file name in this case) into an associative array. The `NR==FNR` is an `awk` idiom that is true only for the first file and `next` means the only this part is executed on the first file of file names. `$1` is used since the leading and trailing spaces are stripped. Since Unix filenames *can* have leading or trailing spaces, this is a rare ambiguity you need to resolve. If you don't want the lines stripped, you would use `$0` instead.
3. `{for (e in fn){ if (base(e)==base($1)){ printf "%s,%s\n", e, $1 }}}` now for any line other than from the first file (where `NR==FNR` is true since `next` skipped this part) loop through the saved file names. Print if the base name is the same.