2

I have a list of videos in a directory that I want to concatenate.

Video1.mpg
Video2.mpg
.
.
.
Video35.mpg

I want to concatenate this in the order of their number without having to write all of them manually to the cat command.

MikeD
  • 810

3 Answers3

1

With zsh and ffmpeg:

files=(Video*.mpg(n))
ffmpeg -f concat -safe 0 -i <(printf 'file %s\n' ${(qq)files}) -c copy output.mpg

(n) in zsh is a glob qualifier to sort numerically. (qq) is a variable expansion flag to quote with single quotes. I won't guarantee that it quotes in the exact same was as expected by ffmpeg if the file names contain single quotes or backslashes or newline characters.

As far as I understand, the above assumes the same codec is used in all the mpg files.

AFAICT, for mpeg files specifically, the files can also be concatenated at the file level and still playable by most players, so you can also simply do (still with zsh):

cat Video*.mpg(n) > output.mpg

While zsh is installed by default in macOS, it is not the default shell you get in a terminal unless you've explicitly changed your login shell from the default of bash. So you'd need to either start zsh first, by entering zsh at the prompt of the bash shell in the terminal, or run:

zsh -c 'cat Video*.mpg(n) > output.mpg'

instead.

0

Use Bash brace expansion.

cat Video{{1..9},{10..35}}.mpg > outputfile

In the future, use 0 padding when naming the files originally, so you can just do:

cat Video{01..35}.mpg > outputfile
Wildcard
  • 36,499
  • Gets me a 'No such file or directory' error. – medicengonzo Mar 15 '17 at 04:25
  • @medicengonzo, then you don't have all the files 1 to 35 and you should edit your question. Or use file globs to only catch the files actually present: cat Video[1-9].mpg Video[0-9][0-9].mpg > outputfile (Globs expand only to existing files; brace expansion is for arbitrary text arguments whether names of existing files or not.) – Wildcard Mar 15 '17 at 04:29
  • 2
    Since the question was tagged OSX, I'll just note that the {01..35} expansion doesn't work on bash 3.2.57, which is what my Mac seems to have by default.. – ilkkachu Mar 15 '17 at 09:35
-1

Here is one way:

cat $(ls Video*.mpg | sort -to -k2 -n )>outputfile  

ls Video*.mpg - lists files based on pattern
sort -to -k2 -n - sorts the files using o as a delimiter, 2nd key, and -n for numeric

*Please realize, using ls on an unknown list of files can be unpredictable, but this is a relatively small and known list, based on the question.

MikeD
  • 810
  • This is exactly the same as the answer you just deleted. Parsing ls is still bad practice, even if it sometimes works. – Wildcard Mar 15 '17 at 02:17
  • My previous answer was cat $(ls Video*.mpg | sed -e "s/Video//" | sort -n | sed -e "s/^/Video/")>outputfile - I simplified it by removing the sed commands, leaving a just the sort. I realize using ls on an unknown list of files can be unpredictable, but this is a relatively small and known list based on the question. – MikeD Mar 15 '17 at 03:22
  • Fair enough, that is true. I regard this site as a learning resource and important place to promote best practices—but if you include a disclaimer to the effect of your comment I'd remove the downvote. (Answers here get read and used long, long after the original asker has moved on.) Or I can add a disclaimer, if you like. – Wildcard Mar 15 '17 at 04:18