1

I am trying to interate over multiple video files that are grouped in directories, and ffmpeg returns errors about paths, it seems like paths are broken, end at first space. Can you point me too what is the problem here? Files and directories have spaces.

$ for f in $(find -type f -name *.mkv); do ffmpeg -n -i "$f" -c:v copy "~/Pobrane/$f" ; done

Loop splits paths by space and takes words as entries. How to fix this?

$ for f in $(find -type f -name *.mkv); do echo "$f"; done
./homeworks/2017-04-03
00-54-57
homework3b.mkv
./homeworks/2017-04-03
00-21-36
homework1.mkv
./homeworks/2017-04-03
ArekBulski
  • 4,520
  • 4
  • 39
  • 61
  • [Don't Read Lines With `for`](http://mywiki.wooledge.org/DontReadLinesWithFor). Also see [BashPitfalls #1](http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29). – Charles Duffy Apr 16 '17 at 16:12
  • (Another useful resource is [Using Find](http://mywiki.wooledge.org/UsingFind)). – Charles Duffy Apr 16 '17 at 16:18

1 Answers1

3

Replacing the Loop

Use

find -type f -name '*.mkv' -exec ffmpeg -n -i {} -c:v copy ~/Pobrane/{} \;

-exec executes the following ffmpeg command for each of the found paths, replacing {} with the current path. The ; informs find that the ffmpeg command ends there.

Quote '*.mkv' in order to pass the literal string to find, which then searches for files ending with *.mkv. If you do not quote the string and have some mkv files laying around in your working directory, the shell will expand the unquoted *.mkv resulting in find -type f -name firstFile.mkv secondFile.mkv ... before starting find.

Do not quote ~. The unquoted ~ expands to your home directory (probably /home/yourname) but the quoted '~' is a directory/file with the literal name ~ .

Creating Parent Directories

How would I add mkdir -p before the ffmpeg call?

You could wrap the mkdir and ffmpeg in one function and execute the function:

myFunction() {
    mkdir -p "$(dirname "$1")"
    ffmpeg -n -i "$1" -c:v copy ~/Pobrane/"$1"
}
export -f myFunction

find -type f -name '*.mkv' -exec bash -c 'myFunction "$0"' {} \;

or use a loop:

find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' file; do
    mkdir -p "$(dirname "$file")"
    ffmpeg -n -i "$file" -c:v copy ~/Pobrane/"$file" 
done
Community
  • 1
  • 1
Socowi
  • 25,550
  • 3
  • 32
  • 54