How to cat multiple files from a list of files in Bash?

xargs cat < files

The advantage of xargs over $(cat) is that cat expands to a huge list of arguments which could fail if you have a lot of files in the list due to Linux' maximum command line length.

Example without caring about #:

printf 'a\nb\nc\n' > files
printf '12\n3\n' > a
printf '4\n56\n' > b
printf  '8\n9\n' > c
xargs cat < files

Output:

12
3
4
56
8
9

More specific example ignoring # as requested by OP:

printf 'a\nb\n#c\n' > files
printf '12\n3\n' > a
printf '4\n56\n' > b
printf  '8\n9\n' > c
grep -v '^#' files | xargs cat

Output:

12
3
4
56

Related: How to pipe list of files returned by find command to cat to view all the files


Or in a simple command

cat $(grep -v '^#' files) > output

#!/bin/bash

files=()
while read; do
    case "$REPLY" in
        \#*|'') continue;;
        *) files+=( "$REPLY" );;
    esac
done < input
cat "${files[@]}"

What's better about this approach is that:

  1. The only external command, cat, only gets executed once.
  2. It's pretty careful to maintain significant whitespace for any given line/filename.

{
  while read file
  do
    #process comments here with continue
    cat "$file"
  done
} < tmp > newfile

Tags:

Loops

File

Bash