8

I need to merge a bunch of mp3 files together. I know that simply doing

cat file1.mp3 >> file2.mp3

seems to work fine (at least it plays back correctly on my Zune anyway).

I'd like to run

cat *.mp3 > merged.mp3

but since there are around 50 separate mp3 files I don't want to be surprised halfway through by a file in the wrong spot (this is an audio book that I don't feel like re-ripping).

I read through the cat man pages and couldn't find if the order of the wildcard operator is defined.

If cat doesn't work for this, is there a simple way (perhaps using ls and xargs) that might be able to do this for me?

javanix
  • 1,270
  • 3
  • 24
  • 40
  • The wild card expansion is performed by your shell (e.g. bash) – MattH Aug 24 '11 at 13:55
  • 2
    Do you know if that expansion in bash is alphabetical by any chance? – javanix Aug 24 '11 at 13:59
  • 1
    Wouldn't a playlist be the usual way to solve this? – Flexo Aug 24 '11 at 14:01
  • 1
    Yes "Pathname Expansion" is alphabetically sorted in bash. (See "Pathname Expansion" section of the bash man page) – MattH Aug 24 '11 at 14:31
  • Normally a playlist would be, but I can't figure out how to get the Zune to remember my spot in a playlist when I go off of the book and listen to something else. However, if I turn it into a single mp3 and place it on the device as an audiobook, it will remember where you are when you pause/shut off the device and resume from there when you open it next time. – javanix Aug 24 '11 at 15:07

2 Answers2

15

Your version (cat *.mp3 > merged.mp3) should work as you'd expect. The *.mp3 is expanded by the shell and will be in alphabetical order.

From the Bash Reference Manual:

After word splitting, unless the -f option has been set, Bash scans each word for the characters ‘*’, ‘?’, and ‘[’. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.

However, do be aware that if you have many files (or long file names) you'll be hampered by the "argument list too long" error.

If that happens, use find instead:

find . -name "*.mp3" -maxdepth 0 -print0 | sort -z | xargs -0 cat > merged.mp3

The -print0 option in find uses a null character as field separators (to properly handle filenames with spaces, as is common with MP3 files), while the -z in sort and -0 in xargs informs the programs of the alternative separator.

Bonus feature: leave out -maxdepth 0 to also include files in sub directories.


However, that method of merging MP3 files would mess up information such as your ID3 headers and duration info. That will affect playability on more picky players such as iTunes (maybe?).

To do it properly, see "A better way to losslessly join MP3 files" or " What is the best way to merge mp3 files?"

Community
  • 1
  • 1
Shawn Chin
  • 84,080
  • 19
  • 162
  • 191
  • This worked well for me. I passed it through the technique listed in [ ["A better way to merge MP3s losslessly"](http://lyncd.com/2011/03/lossless-combine-mp3s/) to get the ID3/duration data working. – javanix Aug 24 '11 at 15:09
  • That method in the link certainly looks simpler. I'll update the answer. – Shawn Chin Aug 24 '11 at 15:11
5

try:

ls | sort | xargs cat > merged.mp3

(Anyway I'm not sure that you can merge mp3 files that way)

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • ls will sort alphabetically unless instructed otherwise. – Peder Klingenberg Aug 24 '11 at 13:58
  • I wanted to merge parts of logs for the same day, but the alphabetical order didn't work for me, as they are named `x.log.1`, ..., `x.log.9`, `x.log.10`, etc. The `-V` option of `sort` has saved the day: `ls | sort -V | xargs cat > merged.log` – Benjamín Valero Oct 15 '20 at 22:19