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

I am new in awk and I do not know if it is possible to write an awk script that does this:

I have hundred of data files that I have to sort. For each one I use the following one-liner:

awk 'ORS=NR%3?" ":"\n" ' file1.tex >  file1_sorted.tex
awk 'ORS=NR%3?" ":"\n" ' file2.tex >  file2_sorted.tex

and I get the output I need. However I would like to have an script to automate this action, taking each file, applying the action and writing the corresponding sorted file.

I would appreciate your help!

share|improve this question
up vote 6 down vote accepted

If you modify the awk code, can be solved by a single awk process and no shell loop:

awk 'FNR==1{if(o)close(o);o=FILENAME;sub(/\.tex/,"_sorted.tex",o)}{ORS=FNR%3?" ":"\n";print>o}' *.tex

Not a beauty, just insignificantly faster.

Explanations as requested in comment.

FNR (file number or record) is similar to NR (number or record), but while NR is a continuous sequence number of all input records, FNR is reset to 1 when processing of a new input file is started.

A gawk 4.0 only alternative for the FNR==1 is the BEGINFILE special pattern.

awk '
FNR==1{   # first record of an input file?
  if(o)close(o);   # was previous output file? close it
  o=FILENAME;sub(/\.tex/,"_sorted.tex",o)   # new output file name
  ORS=FNR%3?" ":"\n";   # set ORS based on FNR (not NR as in the original code)
  print>o   # print to the current output file
' *.tex
share|improve this answer
Thanks @manatwork! That was awesome. Unlike the last answer, I do not get exactly how does this one-liner work, but it did. If you have time, I would thank you if you could explain to me what does FNR==1 do. =) – Nacu Feb 20 '12 at 18:50

You can apply the files in a for loop:

for file in *.tex;
    awk 'ORS=NR%3?" ":"\n"' "$file" > "$(basename "$file")_sorted.tex"

Or on one line:

for file in *.tex; do awk 'ORS=NR%3?" ":"\n"' $file > "$(basename "$file" .tex)_sorted.tex"; done

Since you don't specify which shell, go with the more standard basename instead using the shell specific syntax ${file%%.tex}.

share|improve this answer
That “shell-specific syntax” is in POSIX and is available on practically every unix system that's still under warranty, and many that aren't. – Gilles Feb 19 '12 at 23:55
Thanks @Arcege!, I use emacs as shell. Although your suggestion is pretty understandable, I do not know how to use it. As far as I understand and I have been practiced, one writes an .awk script that you run before the file or folder you want to apply it to. Am I right? I did that, however this seems another kind of script that I do not know how to use. – Nacu Feb 20 '12 at 18:41
You can run a shell inside emacs (<kbd>M-x</kbd>shell) and run the commands above inside that at the prompt. Or open a terminal and run the command there. There are two ways to specify (awk, shell, etc) scripts: either on the command-line or in a file. Your awk command in the posting uses the command-line form; my "one line" command is also a command-line form. – Arcege Feb 20 '12 at 19:15

Old question but given that the last time I saw a single core personal computer was a decade ago, you can use gnu parallel

To solve the shell expansion and interpretation of quotes

my_awk='ORS=NR%3?" ":"\n"' 

Use the proper glob to select the input files. Here I'm using {.} to take out the extension from the output name because I'm appending it afterwards

parallel -jX "awk '$my_awk' {} > {.}_sorted.tex" ::: *.tex

where X is the number of processors you want to use, still you can use 1. This would give you file[1-9]_sorted.tex as outputs

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.