Merge multiple files into one
Concatenate the contents of several files into a single output file.
How to merge multiple files into one in each shell
cat file1.txt file2.txt file3.txt > combined.txtGlobs expand: `cat *.log > all.log` (alphabetical). For numeric-order: `cat $(ls -1v file*.log) > all.log` (-v = natural sort, so `file10.log` comes after `file9.log`, not after `file1.log`). To add separator between files: `awk 'FNR==1 && NR>1 {print "---"} 1' f*.log > all.log`. To DEDUPE while merging: `awk '!seen[$0]++' f*.log > all.log` (preserves first occurrence order).
cat file1.txt file2.txt file3.txt > combined.txtSame external `cat`. zsh-specific glob ordering: `cat file*.log(.On) > all.log` — `(.On)` is a zsh glob qualifier — `.` regular files, `On` order by NAME descending. zsh's glob qualifiers are the cleanest way to sort by mtime / size / type without piping through `sort`/`ls`.
cat file1.txt file2.txt file3.txt > combined.txtSame external `cat`. Fish glob: `cat *.log > all.log` works identically.
Get-Content file1.txt, file2.txt, file3.txt | Set-Content combined.txt`Get-Content` accepts COMMA-separated paths — reads each in order, streams into the pipeline. `Set-Content` writes them concatenated. For globs: `Get-Content *.log | Set-Content all.log`. Default Encoding: pwsh 5.1 writes Windows-1252 / UTF-16; pwsh 6+ writes UTF-8 without BOM. Specify explicitly: `Set-Content -Encoding utf8NoBOM all.log`. For RAW (no line-by-line splitting + faster): `Get-Content -Raw file1.txt, file2.txt | Set-Content combined.txt`.
copy /b file1.txt+file2.txt+file3.txt combined.txt`copy /b` BINARY mode — concatenates byte-for-byte. The `+` syntax merges into a SINGLE output file. Default cmd `copy file1+file2` is TEXT mode + stops at first Ctrl-Z (0x1A) — corrupts binary. Always use `/b` for safety. Globs: `copy /b *.log combined.log` (alphabetical order). To NOT prompt on overwrite: `copy /b /y *.log combined.log`.
Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.
Gotchas & notes
- **Trailing-newline gotcha — files that don't end in `\n`**: `cat a.txt b.txt > out.txt` where `a.txt` has no trailing newline glues `a.txt`'s last line directly onto `b.txt`'s first line: `lastline-of-afirstline-of-b`. Not a bug — `cat` does byte-faithful concat. For safe text-file merging: `awk 1 a.txt b.txt > out.txt` (`awk 1` prints each line + ensures trailing newline). Or `for f in *.log; do cat "$f"; echo; done > all.log` (extra blank between files).
- **Binary vs text mode — Windows cmd `copy`**: default `copy` (no flag) is TEXT mode on cmd — adds Ctrl-Z (0x1A) at end of each input + stops reading at first 0x1A in source. Corrupts binary files (JPGs, ISOs, .docx) silently. Always use `copy /b` for non-text. `xcopy` is BINARY by default — `xcopy /Y file1.bin combined.bin` works without flag.
- **Memory + speed**: `cat *.log > all.log` streams (constant memory, fast). pwsh `Get-Content *.log -Raw | Set-Content all.log` reads each file FULLY into memory then writes — OOM on multi-GB logs. For huge concatenation on pwsh: `[System.IO.File]::ReadAllBytes` per source + `[System.IO.File]::WriteAllBytes` to a `FileStream` (manual streaming). Or shell out: `cmd /c "copy /b a+b+c combined"`.
- **Encoding consistency**: merging files of mixed encodings (UTF-8, UTF-16, Windows-1252) without normalization produces gibberish. Detect with `file -i *.log` (Linux/macOS) — outputs `text/plain; charset=utf-8` per file. Normalize: `iconv -f WINDOWS-1252 -t UTF-8 latin.txt > latin.utf8.txt` before concatenating. pwsh: `Get-Content latin.txt -Encoding windows1252 | Set-Content latin.utf8.txt -Encoding utf8NoBOM`.
Related commands
Related tasks
- Split a large file into pieces— Split a single large file into smaller chunks by byte count or line count.
- Remove duplicate lines from a file— Strip duplicate lines from a file, optionally preserving original order.
- Sort a file by a specific column— Sort lines of a file by the value in a chosen column (numeric or alphabetic).