Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a directory full of files ending with different extensions, how would I list/select only the files ending with .in and corresponding .out that share the same basename?



What I want to select from these files are:

share|improve this question

Since you want .in to be paired with .out, loop through only *.in and check if there is a corresponding .out file, if so, print out both:

for f in *.in; do
  if [[ -f ${f%.in}.out ]]; then
    echo $f
    echo ${f%.in}.out
share|improve this answer
This is how I would have done it. Sweet and simple. I'd simplify it to one line though: for f in *.in; do [[ -e ${f%.in}.out ]] && echo $f ${f%.in}.out; done – rsaw Nov 26 '12 at 15:03

First match against all files, and check if .out file exists, then print the name:

for x in *; do
   if [[ "$x" =~ ^(.*)\.in ]] && [[ -f ${BASH_REMATCH[1]}.out ]];then 
      echo -n "$x ${x%%.in}.out "; 
share|improve this answer
Daaaayumn. I had no idea BASH could save substrings to a variable like that. That BASH_REMATCH array is awesome. Niiice! PS: You could simplify that into one [[ ... && ... ]] expression. – rsaw Nov 26 '12 at 3:44
@ryran, [[ ... ]] & [[ ... ]] is guaranteed to be processed left-to-right. Are you sure that [[ ... && ... ]] is also so guaranteed? (Not so interesting if it merely happens now to be so processed in the current version of bash.) – dubiousjim Nov 26 '12 at 9:53
@dubiousjim: Yes, I'm sure that [[ ... && ...]] is processed as expected. Take a look at the bash man page under the [[ expression ]] section. – rsaw Nov 26 '12 at 14:58
Wouldn't it be more efficient to only select the "*.in" files, e.g. "for x in *.in; do" rather than selecting all files and then checking if the file ends with ".in"? – Daemon of Chaos Nov 26 '12 at 15:00

With zsh:

has_out() [[ -e $REPLY:r.out ]]
ls -ld -- *.in(+has_out)
share|improve this answer

You can list all those files, remove the extensions, filter duplicates and print them:

$ ls | grep '\(\.in\|.out\)$' | sed 's/....$//' \
     | sort | uniq -c | grep '^[\t ]*2' | sed 's/^[\t ]\+2 //'


  • does not need bash
  • does just one expensive operation - directory listing - i.e. does not need to stat(2) each file (as in [[ -f ... ]])

In case the ls already alphabetically sorts its output the sort command can be removed from the pipe. I don't know if POSIX specifies the sorting behavior of a ls.

The pipe prints all the basenames if files with .in and .out extension.

If you then need a list of the corresponding files you have to suffix the list with the previously filtered extensions. For example like this:

$ ls | grep '\(\.in\|.out\)$' | sed 's/....$//' \
     | sort | uniq -c | grep '^[\t ]*2' \
     | sed -e 's/^[\t ]\+2 //' -e 's/$/.in/ ; p; s/in$/out/'
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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