You don't need neither basename nor a loop for this;
You can use -type f
to avoid find
reporting directories in it's result combined with -exec
option to execute directly your command.
Something like this should work for all your mp4 files:
find . -type f -name '*.mp4' -exec bash -c 'ffmpeg -i $0 -q 1 $0'_'%d.jpeg' {} \;
See a small demo test:
$ find . -type f -name 'a*.txt' -exec bash -c 'echo ffmpeg -i $0 ' {} \;
ffmpeg -i ./a.txt
ffmpeg -i ./a spaced file.txt
ffmpeg -i ./aa.txt
ffmpeg -i ./cheatsheets/awk-cheat-sheet-gv.txt
As you can see second file has spaces in the file name, but is handled correctly by find
.
On the contrary such a spaced file will break with a for loop
.
If you insist to make this job with a loop , then this must be a while loop as advised by Fred.
As a modification to Fred solution you can avoid the use of basename using the -printf
capabilities of find
:
while read -r -d '' file;do
ffmpeg -i "$file" -q 1 "${file}_%d.jpeg"
done < <(find . -name "*.mp4" -printf %f\\0)
-printf %f
according to man page of find
prints the file name stripped, and appending \\0
(null char) after each file name we ensure correct filenames handling even if names contain spaces or other special chars.
Small test:
$ while read -r -d '' file;do echo "ffmpeg -i $file -q 1 ${file}_%d.jpeg";done < <(find . -name "a*.txt" -printf %f\\0)
ffmpeg -i a.txt -q 1 a.txt_%d.jpeg
ffmpeg -i a spaced file.txt -q 1 a spaced file.txt_%d.jpeg
ffmpeg -i aa.txt -q 1 aa.txt_%d.jpeg
ffmpeg -i awk-cheat-sheet-gv.txt -q 1 awk-cheat-sheet-gv.txt_%d.jpeg