Currently I use multiple lines to append content into a combined file, e.g.

./myprogram 1.txt > Out.txt # Overwrite for the 1st file
./myprogram 2.txt >> Out.txt
./myprogram 3.txt >> Out.txt
./myprogram 4.txt >> Out.txt

Is it possible to replace by one-liner?

migrated from serverfault.com Aug 8 '14 at 13:36

This question came from our site for system and network administrators.

  • 4
    I will never understand why people insist on magical one liners instead of putting an easy to understand solution into a shell script. – Sven Aug 7 '14 at 11:21
  • Because it is error prone, the first line is a single ">", and the rest of lines are ">>", I've several times used ">>" in the first line due to copy and paste, so I am looking for more elegant solution. does it make sense to you? – Ryan Aug 7 '14 at 15:52
  • Creating a shell script with good formatting, indentation and comments is better anyway because it's easier to understand, and therefore less error prone then an endless one-liner. If you need to do the above more than once, it will also save a lot of time. – Sven Aug 7 '14 at 16:00
  • @Ryan you could begin with cat /dev/null > Out.txt and have >> on all invocations of ./myprogram. – MattBianco Aug 8 '14 at 14:46
(./myprogram 1.txt; ./myprogram 2.txt; ./myprogram 3.txt; ./myprogram 4.txt) > out.txt
  • +1 Bonus, this works in bash, sh, csh/tcsh, zsh, and probably more... – Chris S Aug 8 '14 at 13:46

It depends on what you want to do and how your program handle input args.

But let's say you have /path/to/myprogram.sh who look like this one :

#!/bin/bash
echo "Processing file ${1?missing input file}"

You could do the following

find /path/to/inputfiles -name "*.txt" -exec /path/to/myprogram.sh {} \; > Out.txt

Or within bash (or any Bourne-like shell):

for i in *.txt; do /path/to/myprogram.sh "$i"; done > Out.txt

(I use for-loop or find because it will be much more convenient if you have 1000 input files instead of the 4 files in your example)

  • 1
    careful with the *.txt if Out.txt already exists. – MattBianco Aug 8 '14 at 14:44

Very similar to Per's answer, but maintains the layout of the original:

{
    ./myprogram 1.txt
    ./myprogram 2.txt
    ./myprogram 3.txt
    ./myprogram 4.txt
} > Out.txt

http://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping

myprogram-wrapper.sh:

#!/bin/sh -
while test $# -ge 1
do
  ./myprogram $1
  shift
done

invoke with ./myprogram-wrapper.sh 1.txt 2.txt 3.txt 4.txt > Out.txt

To make a reusable wrapper:

#!/bin/sh -
prog=$1
shift
while test $# -ge 1
do
  ${prog} $1
  shift
done

and invoke like wrapper ./mycommand 1.txt 2.txt 3.txt 4.txt > Out.txt

This is of course cheating, since the script itself is not a oneliner, but I thought you might like it anyway.

I find this solution more elegant:

FILE=/tmp/file.log

exec >> $FILE
./myprogram 1.txt
./myprogram 2.txt
./myprogram 3.txt
./myprogram 4.txt
exec 1<&2

echo 'Normal output has returned!'

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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