1

This question already has an answer here:

I'm trying to convert all wav and mp3 files to ogg files recursively with find and FFmpeg. I have made the following bash script to do so:

#!/usr/bin/env bash

# Converts samples to ogg

find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \;

This however errors in:

${$(basename "{}")%.*}.ogg: bad substitution

How would I need to format the last substitution to make it give back the basename of the file suffixed with .ogg, and why does this not work?

marked as duplicate by Gilles bash Jun 11 '16 at 11:57

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3

You seem to assume that --execdir invokes a (Bash) shell that then invokes ffmpeg. That is not the case:

   -exec command ;
          Execute  command;  true  if 0 status is returned.  All following
          arguments to find are taken to be arguments to the command until
          an  argument  consisting of `;' is encountered.  The string `{}'
          is replaced by the current file name being processed  everywhere
          it occurs in the arguments to the command, not just in arguments
          where it is alone, as in some versions of find.

ffmpeg is invoked by find and it (ffmpeg) doesn't know how to handle your special syntax.

I would just make small bash script that can handle one conversion based on the input filename only and use that as a parameter for -execdir.

2

I recently wrote an example of stuffing a shell one-liner into a find command, and this is another use case for the same.

Instead of:

find samples \( -iname '*.wav' -o -iname '*.mp3' \) -execdir ffmpeg -i "$(basename "{}")" -qscale:a 6 "${$(basename "{}")%.*}.ogg" \;

Try:

find samples \( -iname '*.wav' -o -iname '*.mp3' \) -exec sh -c 'ffmpeg -i "$1" -qscale:a 6 "${1%.*}.ogg"' find-sh {} \;

Note that find-sh is arbitrary text; in the position where it is, it gets set as the shell's $0. This doesn't matter much but it's used for error reporting, so it's good to have something descriptive there. I think find-sh is a pretty good name.

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