Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

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

And with the oldest file on bottom?

Also, if I do this, is it also possible to strip out the redundant headers contained within each HTML file? I'm seeing myself concatenate a lot of HTML files up, and it would be nice to reduce the file size of the ultimate file a bit.

share|improve this question
up vote 18 down vote accepted

To concatenate files you use

cat file1 file2 file3 ...

To get a list of quoted filenames sorted by time, newest first, you use

ls -t

Putting it all together,

cat $(ls -t) > outputfile

You might want to give some arguments to ls (eg, *.html).

But if you have filenames with spaces in them, this will not work. My file.html will be assumed to be two filenames: My and file.html. You can make ls quote the filenames, and then use xargs, who understands the quoting, to pass the arguments to cat.

ls -tQ | xargs cat

As for your second question, filtering out parts of files isn't difficult, but it depends on what exactly you want to strip out. What are the “redundant headers”?

share|improve this answer
    
This isn't working on my debian system... I have to use cat $(ls -t) > outputfile, otherwise cat rejects the quoted file names – Mike Pennington Jun 16 '12 at 9:50
1  
My mistake. I always get caught on these things. See updated answer. – angus Jun 16 '12 at 11:19
    
Oh - by redundant headers I mean things that are normally put in some header.php/footer.php file, but which are saved separately when saved to HTML (and can really increase the file size when you mass-download PHP pages). – InquilineKea Jun 16 '12 at 15:03
    
cat $(ls -t) is also vulnerable to filename expansion. If there's a filename with an *, or ?, or a bracket expression (e.g. file-[old].html); and if the filename interpreted as a pattern matches other filenames; the approach will produce an incorrect list. set -f would address this deficiency. – Barefoot IO Feb 20 at 19:42
    
ls -Q may produce output which is not suitable for xargs. For example, "foo" becomes "\"foo\"", but xargs does not understand escaped double quotes within double quoted strings. – Barefoot IO Feb 20 at 20:04

The easiest way of listing files in an order other than lexicographic is with zsh glob qualifiers. Without zsh, you can use ls, but parsing the output of ls is fraught with dangers.

cat *(om)

If you want to strip some lines, use sed or awk or perl. For example, to take the <head> from the first file and combine the <body> parts from the other files, assuming that the <body> and </body> tags are alone on a line in every file:

{
  sed -e '/<\/body>/ q' *.html(om[2])
  sed -e '1,/<body>/ d' -e '/<\/body>/,$ d' *.html(om[3,-1])
  echo '</body>'
  echo '</html>'
} >concatenated.html

Explanation:

  • First, concatenated.html is created. It is therefore the youngest *.html file (assuming no file has a date in the future.
  • Then copy from the second-youngest *.html file, but quit at the </body> line.
  • Then copy from the other files, but skip everything down to the <body> line and starting with the </body> line.
  • Finally produce the last closing tags.
share|improve this answer

Solution given by @angus is good but will have issues if there are directories in the folder this will fix it.

cat $(ls -tpa | grep -v / )

share|improve this answer
    
Caveat: This answer is also vulnerable to pathname expansion, as explained in my comment to angus' answer. – Barefoot IO Feb 20 at 19:45
    
Unless cat's exit status is tested, a directory argument should be inconsequential. cat will simply emit a message to stderr and proceed to the next argument. – Barefoot IO Feb 20 at 20:15

Your Answer

 
discard

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.