0

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

/temp/test1.xml
/temp/test2.xml
/temp/test3.xml
.........
/temp/test49.xml
/temp/test50.xml

and

/temp/test1.msg
/temp/test2.msg
/temp/test3.msg
.........
/temp/test49.msg
/temp/test50.msg

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.

4
  • This would be better asked on unix.stackexchange.com
    – sashoalm
    Commented Jun 7, 2013 at 6:08
  • 2
    There's no reason why a shell programming question cannot be asked on SO. Commented Jun 7, 2013 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.) Commented Jun 7, 2013 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
    Commented Jun 7, 2013 at 6:34

5 Answers 5

4
for f in *xml ; do
  cat "$f" "${f/.xml/.msg}"
done > OUTPUTFILE

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.

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

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

file1
file2
file with spaces 3
...
filen

to:

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/$/ \\/.

0
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
done
1
  • The {1..50} expression is a Bashism, too.
    – tripleee
    Commented Jun 7, 2013 at 7:46
0

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
0

If it is a normal sequence you can do this:

in bash:

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

or if you have the utility seq

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

You must log in to answer this question.