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 Jun 16 '14 at 11:55

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
| improve this answer | |
  • 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 Jun 16 '14 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"
| improve this answer | |
  • 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 Jun 16 '14 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 Jun 16 '14 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.