45

As it was suggested here I am using cat command to concatenate several .mp3 files into one .mp3 file.

Imagine, I have following .mp3 files in the current folder:

001001.mp3 001002.mp3 001003.mp3 001004.mp3 001005.mp3

or, like this:

096001.mp3 096002.mp3 096003.mp3 096004.mp3

I need to concatenate these .mp3 files in there ascending sequence, i.e. 001001.mp3+001002.mp3+001003.mp3+etc.

In order to join these .mp3 files into one I am executing following command in the current folder:

cat *.mp3 > final.mp3

I tested the final .mp3 file and it is what I am expected, but I need to be sure that above command picks files in there ascending sequence.

Can I be sure that above command always concatenates files in the ascending sequence?

Thank you Sir!

46

cat is not the right tool for this job. The MP3 format has all sorts of junk that can lurk at the front and end of the file and this needs to be strippe out. mp3wrap is what you want. It will exclude any metadata in the files and stick the audio together.

sudo apt-get install mp3wrap
mp3wrap output.mp3 *.mp3

Before you do that, run ls *.mp3 to check that they're in the correct order. When I originally wrote this answer (over six years ago!) wildcard globs apparently didn't behave well but I think they do now.

You might need to rename the files if for example, they are numbered but aren't zero-padded, {1-11}.mp3 would be sorted by 1 10 11 2 3 4 5 6 7 8 9. This can be fixed easily.

  • 2
    Right - cat will mangle the mp3 file format by "creating an array" (as it were) of mp3 files within a single mp3 file. But it seems to work if the player software is smart enough. – user8290 Jan 8 '11 at 1:25
  • This worked better for me, because it handles mp3s with spaces in the filename: find . -maxdepth 1 -iname '*.mp3' -print0 | sort -z | xargs -0 mp3wrap output.mp3 – bmaupin Jul 31 '14 at 1:25
  • @bmaupin A fair point but I'm not sure why I wasn't just using Bash's wildcard expansion. *.mp3 should suffice (and works with spaces). – Oli Jul 31 '14 at 7:49
  • Available for mac from brew package manager! $ brew install mp3wrap. – Rubens Apr 4 '16 at 16:14
  • 1
    In bash, *.mp3 is guaranteed to preserve alphabetical order. If your files are named 09.mp3, 10.mp3, 11.mp3, that's probably what you want. If your files are named 9.mp3, 10.mp3, 11.mp3, that's probably not what you want, but you can do `ls *.mp3 | sort -n`. – Jo Liss Jul 23 '16 at 17:48
25

mp3wrap seems to be a decent enough solution, but when I played the resulting file, the timestamp wasn't correct. It seems like mp3wrap is best used when you're joining mp3s into a file that you know you'll want to split later.

I simply wanted to permanently concatenate some mp3s together. I ended up using ffmpeg to concatenate the files:

  1. First, install ffmpeg

    • Ubuntu 15.04+

      sudo apt install ffmpeg
      
    • Ubuntu 14.10 and below
      Go to http://ffmpeg.org/download.html, download one of the static builds, untar it, and copy to /usr/local/bin

  2. ffmpeg -i "concat:file1.mp3|file2.mp3" -acodec copy output.mp3

More info: https://trac.ffmpeg.org/wiki/Concatenate#protocol
https://superuser.com/a/314245

8

As previously suggested, mp3wrap is a good solution. It may not work all of the time though. As far as I know, mp3wrap assumes that all the input files have the same characteristics such as VBR vs CBR, bitrate, and so on. If this assumption isn't met, it is likely to fail. In that case, the only solution would be to decode all the mp3files to a raw format like .wav, concatenate them with a program like sox and finish by re-encoding all to mp3.

  • Note that re-encoding mp3 files (also know as "transcoding") will result in a quality loss. I would not recommend it. – Martin Tournoij May 31 at 3:51
5

It does an alphabetical sort based on single characters. That means that "01" comes before "1", since nought has a lower value than one.

Here's an example. I've got a directory with files named 1, 2, 3, 04, 05, and 06. They are text files that contain their own file names:

test$ cat *
04
05
06
1
2
3

So, yes it will; but you need to make sure that all your files are 'padded' properly.

This nifty line of bash script will let you visually compare the file names, making it very easy to spot any mistakes:

for f in $(ls); do printf "%05s\n" "$f"; done

It's output will look like this:

   04
   05
   06
    1
    2
    3

If they aren't, you will need to pad the file names: Bash script to pad file names on StackOverflow explains how to do it.


Edit. Vote for Oli's answer, it's much better. :P
I'll leave mine because it add something, but you should use his solution,

mp3wrap output.mp3 `ls -1 *.mp3 | sort`

Keep in mind that sort will still sort things in the way I described above, you will still need to pad file-names if they aren't equal in length.

4

Most people are suggesting mp3wrap, but it has downsides: the file generated does not report its full length in some players, and then you cannot seek past that point.

mp3cat does the job fast and well, as far as I can tell. It can be downloaded in http://mulholland.xyz/dev/mp3cat/, and used as follows:

mp3cat file1.mp3 file2.mp3 file3.mp3

another possibility would be sox

sudo apt-get install sox libsox-fmt-mp3
sox file1.mp3 file2.mp3 target.mp3

but it seems very slow (possibily it decodes and reencodes the audio?)

3

I found the online service audio-joiner to work very well and preserve the correct time-stamp (contrary to mp3wrap).

0

You might wanna try using a dedicated audio editing program (like Audacity)

0

I love bmaupin's comment, yet it could produce natural sort of (version) numbers by using sort -V:

find . -maxdepth 1 -iname '*.mp3' -print0 | sort -Vz | xargs -0 mp3wrap ../tmp.mp3

and you don't have to deal with special characters like ' " () [] {} in the filename.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.