Super User is a question and answer site for computer enthusiasts and power users. 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

For example: In my /temp directory I have 100 files.. 50 with the extension of .msg and 50 with .xml.




In a text file, I would like to output a combination of the contents of the .xml and .msg files one after the other. For example the output file should look like:

content of test1.xml
content of test1.msg
content of test2.xml
content of test2.msg
content of test3.xml
content of test3.msg
content of test49.xml
content of test49.msg
content of test50.xml
content of test50.msg

in this /temp directory there will always be an equal number of .msg and .xml files. Additionally will it be possible to show the path or the file name before the content in the output file? for example:

text1.xml: content of test1.xml 
text1.msg: content of test1.msg
text2.xml: content of test2.xml
text2.msg: content of test2.msg
text3.xml: content of test3.xml
text3.msg: content of test3.msg
text49.xml: content of test49.xml
text49.msg: content of test49.msg
text50.xml: content of test50.xml
text50.msg: content of test50.msg

I have tried a simple pipe to file

cat * > text.txt

but this does not give required result. In the output file, it first lists the content of all the *.xml files then the *.msg files.

Please assist.

share|improve this question

migrated from Jun 8 '13 at 10:37

This question came from our site for professional and enthusiast programmers.

This would be better asked on – sashoalm Jun 7 '13 at 6:08
There's no reason why a shell programming question cannot be asked on SO. – Jonathan Leffler Jun 7 '13 at 6:22
I could see it listing the message file before the XML file for each pair, but I really don't see how cat * could list all the XML files before all the message files. Can you elaborate on that? (Also, your cat command has no pipes whatsoever; it only uses I/O redirection.) – Jonathan Leffler Jun 7 '13 at 6:24
Apologies.. there is no use of the pipe. when I run the 'cat *' command it gives me all the .xml and then the .msg files in the output file. This could possibly because the way it is in the /temp directory – Chor419 Jun 7 '13 at 6:34
for f in *xml ; do
  cat "$f" "${f/.xml/.msg}"

Might work for you, if you are using the bash shell. Otherwise (other POSIX shells) use: cat "$f" "${f%.xml}.msg" instead of the above cat line.

share|improve this answer
when i run the script with the above i get './testScript[3]: ${f/.xml/.msg}: bad substitution ' – Chor419 Jun 7 '13 at 6:27
The error message indicates you are not using Bash. Try something like cat "$f" "$(basename "$f" .xml).msg") instead then. – tripleee Jun 7 '13 at 7:45
@tripleee is correct, you are getting that error, because of the used shell. – Zsolt Botykai Jun 7 '13 at 12:21
${f%.xml}.msg should work in any POSIX shell (${f/.xml/.msg} is a bashism). – chepner Jun 7 '13 at 13:29

In this kinds of situations, it often makes sense to proceed as follows:

  1. List all the files into a text file:

    $ ls > files
  2. Edit the text file, to remove unwanted files and to arrange the remaining ones into the exact order that you want.

  3. Then just do this (assuming none of the files have spaces or funny characters in their names):

    $ cat $(cat files) > bigfile

A variation on this approach is to change the text file into one big command, from

file with spaces 3


cat \
file1 \
file2 \
"file with spaces 3" \
... \
filen \
> bigfile

Then just source the file as a script:

$ . ./files

A space and backslash can be added to every line in the buffer in vi using :%s/$/ \\/.

share|improve this answer
for i in {1..50}; do
    echo "text$i.xml: `cat text$i.xml`" >> output.txt
    echo "text$i.msg: `cat text$i.msg`" >> output.txt
share|improve this answer
The {1..50} expression is a Bashism, too. – tripleee Jun 7 '13 at 7:46

This seems to work:

ls test* | awk -F. 'NR%2==0 {printf("echo %s.msg:; cat %s.msg\necho %s.xml:; cat %s.xml\n",$1,$1,$1,$1)}' | sh
share|improve this answer

If it is a normal sequence you can do this:

in bash:

for ITER in {1..50}
    cat test${ITER}.xml
    cat test${ITER}.msg
done > test.txt

or if you have the utility seq

for ITER in $(seq 1 50)
    cat test${ITER}.xml
    cat test${ITER}.msg
done > test.txt
share|improve this answer

You must log in to answer this question.