0

I try to write a simple transcoding script for VHS backups with ffmpeg. But I fail to handle spaces in filenames.

I build my ffmpeg command together in the script and echo it and when I copy paste the echoed command it works, but not diretcly from the script.

Has anayone a idea whats wrong with my script?

Script:

#!/bin/bash
# VHStoMP4Backup Script

INPUT=$1
OUTPUT="/Volumes/Data/oliver/Video/Encodiert/${2}"

command="ffmpeg \
    -i \"$INPUT\" \
    -vcodec copy \
    -acodec copy \
    \"$OUTPUT\""


if [ ! -z "$1" ] && [ ! -z "$2" ] ;
then
    echo ${command}$'\n'
    ${command}
else
    echo "missing parameters"
    echo "Usage: script INPUT_FILENAME OUTPUT_FILENAME"
fi

exit

Script calling:

./VHStoMP4Backup.sh /Volumes/Data/oliver/Video/RAW\ Aufnahmen/Ewelina\ -\ Kasette\ 1.dv ewe.mp4

Commandline output

olivers-mac-pro:Desktop oliver$ ./VHStoMP4Backup.sh /Volumes/Data/oliver/Video/RAW\ Aufnahmen/Ewelina\ -\ Kasette\ 1.dv ewe.mp4
    ffmpeg -i "/Volumes/Data/oliver/Video/RAW Aufnahmen/Ewelina - Kasette 1.dv" -vcodec copy -acodec copy "/Volumes/Data/oliver/Video/Encodiert/ewe.mp4"

    ffmpeg version git-2016-04-16-60517c3 Copyright (c) 2000-2016 the FFmpeg developers
      built with Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
      configuration: --prefix=/usr/local/Cellar/ffmpeg/HEAD --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libvorbis --enable-libvpx --enable-librtmp --enable-libfaac --enable-libass --enable-libssh --enable-libspeex --enable-libfdk-aac --enable-openssl --enable-libopus --enable-libvidstab --enable-libx265 --enable-nonfree --enable-vda
      libavutil      55. 22.100 / 55. 22.100
      libavcodec     57. 34.102 / 57. 34.102
      libavformat    57. 34.101 / 57. 34.101
      libavdevice    57.  0.101 / 57.  0.101
      libavfilter     6. 42.100 /  6. 42.100
      libavresample   3.  0.  0 /  3.  0.  0
      libswscale      4.  1.100 /  4.  1.100
      libswresample   2.  0.101 /  2.  0.101
      libpostproc    54.  0.100 / 54.  0.100
    "/Volumes/Data/oliver/Video/RAW: No such file or directory
kyromoto
  • 71
  • 1
  • 1
  • 8
  • See also http://stackoverflow.com/questions/12136948/in-bash-why-do-shell-commands-ignore-quotes-in-arguments-when-the-arguments-are – tripleee Jul 22 '16 at 19:42

1 Answers1

1

Never store a command and its arguments in a regular variable, expecting to execute the command simply by expanding the variable.

Use an array to store the arguments, then expand the array when you call the actual command.

if [ $# -lt 3 ]; then
    echo "missing parameters"
    echo "Usage: script INPUT_FILENAME OUTPUT_FILENAME"
else
    INPUT=$1
    OUTPUT="/Volumes/Data/oliver/Video/Encodiert/${2}"

    args=( -i "$INPUT" -vcodec -acodec "$OUTPUT" )
    ffmpeg "${args[@]}"
fi

You need to do a little more work to log the command properly, but that is a small price to pay for safe, correct code.

printf 'ffmpeg'
printf ' %q' "${args[@]}"
printf '\n'

(The logged command won't look exactly like you expect, but it can be used as a valid command line to run the same command. In particular, the %q specifier tends to escape characters individually with a backslash instead of putting longer strings in quotes.)

chepner
  • 497,756
  • 71
  • 530
  • 681