22

I have saved many documents as txt. I want to print them together so first I want them together in a single file. The order doesn't matter in this case.

I want a solution that does not involve typing the names of the files to be merged, but one that would just merge all txt files within the folder.

Can I do it with a command or some GUI?


I looked here. Don't know how to use join.

8 Answers8

43

Use cat with output redirection. Syntax: cat file [file] [[file] ...] > joined-file.

Example with just two files (you can have many more):

$ echo "some text in a file" > file1
$ echo "another file with some text" > file2
$ cat file1 file2 > mergedfiles
$ cat mergedfiles
some text in a file
another file with some text

In case you have "many documents", make use of shell globbing (patterns):

cat input-files-dir/* > joined-file

This will join all files in that directory to the current directory (preventing it to match the output file itself). It is totally independent to the use of cat and output redirection - it's just Bash providing all the files as arguments to cat.


File types

It will just glue (join) files together as you would do with paper and tape. It does not care about the actual file format being capable of handling this. It will work for text files, but not for PDFs, ODTs, etc. Well, it will glue them together, but it's not a valid PDF/ODT anymore.


Order of joining

As phoibos pointed out the shell globbing will result in alphabetical order of file names. This is how Bash and shell globbing works.


Addendum about input file is output file error

When the pattern of the input files matches the very same file as being output, this will cause an error. It's a safety feature. Example: cat *.txt > out.txt run the second time will cause this.

What you can do about it:

  • Choose a more specific pattern to match the actual input files, not matching the output name. Example: input files pattern *.txt with output file output.out will not collide.
  • Work in different directories. In the example above I've used a separate input-files-dir directory to place all files in, and output to the current working directory. This makes it impossible to get this error.
gertvdijk
  • 67,947
  • @cipricus Yes, but that's very basic shell globbing (patterns). Try out your patterns using ls to just list the matches. E.g. ls *.txt to see what is being matched. – gertvdijk Feb 02 '13 at 13:23
  • @cipricus Shouldn't it be cat .txt > joined ? But what if they don't have the same extension? Then probably they can be moved to a new sub-folder where you can simply join all files there as above or with a command like cat > joined. Or use a simple nautilus-script to join all selected files? – Sadi Feb 02 '13 at 13:27
  • @cipricus D'Oh! :) You already have the output file there. It's being matched as well! Read my comments and the error output please. Exactly this is what I wanted to prevent by my command using a subdir. – gertvdijk Feb 02 '13 at 13:33
  • 2
    @cipricus How about cat *.txt > JoinedFile.txt ? – Sadi Feb 02 '13 at 13:34
  • @Sadi That *.txt will match the output file JoinedFile.txt as well! – gertvdijk Feb 02 '13 at 13:35
  • @cipricus Re-run it and you'll get the same error. Use common sense! – gertvdijk Feb 02 '13 at 13:38
  • If cat catches JoinedFile.txt as well then output name should be without extension, right? – Sadi Feb 02 '13 at 13:38
  • 1
    This is more common sense actually, cat first catches all .txt files and second it joins them and third it creates a new .txt file which cannot be caught at the first step ;-) – Sadi Feb 02 '13 at 13:42
  • @Sadi Now re-run it. – gertvdijk Feb 02 '13 at 13:43
  • @cipricus You're simply wrong and you don't understand it, clearly. documents-dir/* only matches inside that directory. The output is going to the current directory. There is no way that the input files consist of any output file here. You must be doing something different. – gertvdijk Feb 02 '13 at 14:10
  • 1
    @cipricus It just joins files. Like you would by using pieces of paper with glue and tape! Most "documents" file formats like PDF, which are compressed do not allow this. Use a PDF editor. But anyway, your question was about text files. – gertvdijk Feb 02 '13 at 14:25
  • 1
    I fully understand that the method you suggest (creating a subdir, moving files and then joining) might be a better way in some cases. But if we just want to join all the text files (all having .txt extension) in the current directory cat *.txt > JoinedFile.txt does the job perfectly. I just tested it out of curiosity and it works, and it seems cipricus has also found the same result. ( And the system has begun complaining that we shouldn't be chatting here, otherwise I would ask if you can teach this novice how you can use formatting in these comments without a toolbar ;-) – Sadi Feb 02 '13 at 17:29
  • @Sadi: a new answer appeared that is just what you said in the comment. would you care adding that comment as an answer? as they say i just want to keep it simple, and not only that simple command puts all the rest to shame, but is adjustable to work in context menu and to be adapted to selected files only - which is more than i expected - as you may see in my own answer (complementary to your comment, as a matter of fact). as for me being a novice in this geeky thing, i confess it gladly; albeit i prize myself literate, being easily taught is not easy betting –  Feb 02 '13 at 22:35
  • If you deliberately want to have one file be both input and output, you can use sponge to do this: cat one.txt two.txt | sponge one.txt, instead of cat one.txt two.txt > one.txt – Flimm Feb 05 '13 at 20:57
12

A simple way to do that is by using cat:

cat file1 file2 > joined_file

If you just issue cat file1 file2 you'll see both files on the standard output. By using >, you're just redirecting the standard output to a file. That will work also with another commands.

  • Please read the question. You are telling to specify individual file names, which the OP specifically didn't want to do! – Sri Feb 06 '13 at 03:48
  • 2
    That was not in the original question. I've not updated my answer since more complete answers appeared. – Jorge Suárez de Lis Feb 06 '13 at 08:37
  • @JorgeSuárezdeLis While this answer doesn't directly help OP with his/her question, please do note that this answer probably will help someone else who just has a few files they'd like to merge. (oh hey, like me! thank you! ^-^) +1 – Souta Feb 07 '13 at 22:54
  • @JorgeSuárezdeLis Indeed. You've answered revision 2 of the question perfectly fine. A few minutes later, revision 3, changed the requirements about answers. – gertvdijk Feb 08 '13 at 00:04
5

Do it with a simple loop:

for i in *.txt; do cat "$i" >> complete.txt; done

>> appends to the file.

Note: If for some reason you have to run the command again, you have to remove complete.txt, otherwise you'd write the file to itself, which doesn't work.

phoibos
  • 21,456
4

If the files you want to combine all end in .txt, keep it simple:

cat *.txt > combined.txt

If the directory only contains text files, it's also simple:

cat * > combined.txt

(Note that once you create combined.txt, doing it again would include it in the expansion of *, leading to odd behavior).

If you want to select some files in the directory and not others, it's best if the filenames allow you to distinguish which ones you want. If not, you can get fancy with find. But I doubt you need to go that far.

alexis
  • 1,028
  • thnx. if you look at the comments to the accepted answer, Sadi suggested exactly that in a comment. if your answer had been the first yours would have been what i need. take a look at mine too: added that in custom menu –  Feb 02 '13 at 22:04
  • Thanks for the feedback. Yeah, I see it now, it was a bit obscured... – alexis Feb 03 '13 at 00:18
4

Thunar custom action script written by cipricus also inspired me to write a similar Nautilus script and I thought it might be useful for others who look at this Q&A for reference on this subject. So here it is:

#!/bin/sh
#Nautilus Script to join selected text files in a single file and open the joined file with default text editor
#
IFS=$'\n'
FILENAME="JoinedFile_$(date +%Y-%m-%d-%H-%M-%S).txt"
cat "$@" > "$FILENAME"
xdg-open "$FILENAME"
Sadi
  • 10,996
  • @David Foerster Thanks for the edit. I didn't have any problems with the old version (with my limited test cases) and I don't see any problem with this improved version either. Sorry if I caused any inconvenience due to a flaw in the previous version. – Sadi Aug 21 '15 at 12:27
  • It wasn't flawed, but it contained an unnecessary loop, which made the code more difficult to understand, imho. – David Foerster Aug 21 '15 at 22:56
2

This is a complement and a variation to the other answers, related to putting these solutions to work in Thunar's custom's actions.

Not all of them are usable in this way, but some are.

I thought that most interesting would be to be able to merge selected files from Thunar's context menu.

This is a variation from what was suggested by Sadi in a comment to gertvdijk's answer :

   cat %N > JoinedFile

Only selected files will be joined. Restrict appearance conditions to text files.

enter image description here

enter image description here


Special thanks to Sadi whose comment provided me with the most clear and up-to-point solution to my problem.

I accepted gertvdijk's answer as definitive. Not only it was the occasion to Sadi's comment, but is seems to be of further value to others, providing a well argued and complete solution (albeit somewhat above my CLI reading skills).

2

You could try find command also,

find . -name "*.txt" -type f -exec cat {} + > file

It finds .txt files inside the current directory and execute cat command on each founded file. Finally the whole output was redirected to the filename file(created within the current directly itself).

Explanation:

.                  # current directory

-name              # helps to find only .txt files.

-type f            # Only files

-exec cat {} +     # helps to run cat command on the founded .txt files.

>                  # Output redirection operator

file               # to store final output.
David Foerster
  • 36,264
  • 56
  • 94
  • 147
Avinash Raj
  • 78,556
-2

You could also just use an online utility such as merge-files-online.com

StackMan
  • 5
  • 1