I'm running tests of a variable-size-and-contents test set. Data files are added and removed frequently. I'm looking for an automated way of gathering a file list.

All files are in subdirectories of D; I need the full directory and name added to a text file. However, I only need those files that have a "paired" file, which has the same filename but a different extension (so... different filename, but in a structured way). So, if there is a MyFileName.A and MyFileName.B, then I want D/.../MyFileName added to the file list.

There are .A files without .B files, but no .B files without .A files. If a .A has a .B file, then both files are in the same directory.

Any advice?

  • 1
    ls D/*.B | sed 's/\.B$//' > file_list.txt?
    – mr_tron
    Commented Jun 16, 2014 at 11:55

3 Answers 3


If none of the filenames contain any newlines, you can do:

find D -type f \( -name '*.A' -o -name '*.B' \) |
  sed 's/\.[^.]*$//' |
  sort |
  uniq -d >paired_files

This should work in the more general case where there are .B files without .A files.

To handle any filename using recent GNU tools:

find D -type f \( -name '*.A' -o -name '*.B' \) -print0 |
  sed -z 's/\.[^.]*$//' |
  sort -z |
  uniq -dz |
  tr '\0' '\n' >paired_files
  • Works perfectly, thanks! Flagged this as the answer as well as richard's, because this one generally applicable whereas richard's uses the very obvious property of if B then A
    – Gaminic
    Commented Jun 16, 2014 at 13:38

If you statement is true “there are no .B files without .A files.”, then get a list of .B files and remove the extension.

find $directory-to-search -name "*.B" | sed -r -e "s~(.*)\.B~\1~g"
  • 1
    Note that -r to enable extended expressions is not standardised. GNU sed uses it but OSX sed uses -E instead. Others may not implement extended expressions at all.
    – Graeme
    Commented Jun 16, 2014 at 12:13
  • I can't believe I didn't think of that. I guess that's why you should reexamine your assumptions when the problem changes.
    – Gaminic
    Commented Jun 16, 2014 at 13:34

With zsh:

print -rl mydir/**/*.A(.e_'REPLY=$REPLY:r; [[ -f $REPLY.B ]]'_)

:r removes the extension, so if the content of $REPLY was mydir/somedir/somefile.A after running REPLY=$REPLY:r its content becomes mydir/somedir/somefile;
the rest is similar to this answer.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .