Reputation: 251
I have many folders with .mp4 files. I wrote a script that takes the mp4 files and converts them into 1 jpeg image per frame. Critically, the output of this script (retained file name, with _frame number appended to the end) goes into a newly created folder with the file basename:
#!/bin/bash
for f in *.mp4; do mkdir -p "${f%.*}" && ffmpeg -i ${f} -start_number 000 "${f%.*}/${f}_%03d.jpg"; done
I can run this for every parent folder one at a time no problem but I would like to just run it once and get it to run recursively.
I changed the code to:
#!/bin/bash
for f in *.mp4/; do mkdir -p "${f%.*}" && ffmpeg -i ${f} -start_number 000 "${f%.*}/${f}_%03d.jpg"; done
and tried playing with the mkdir part (by adding ./) but no matter what I do, I get the following error.
mkdir: cannot create directory ‘*’: Invalid argument
Is there anything I need to do to allow mkdir to create the appropriate new folders in their respective subfolders?
The file structure is as follows:
parent folder
└── videos_1
├── videos_1_basename_1.mp4
└── videos_2_basename_2.mp4
└── videos_2
├── videos_2_basename_1.mp4
└── videos_2_basename_2.mp4
.sh script
Upvotes: 1
Views: 1063
Reputation: 28945
You can use the globstar
bash option to recurse in sub-directories and also the nullglob
option such that the pattern expands as null instead of itself (the reason for your error as explained in another answer):
#!/usr/bin/env bash
shopt -s globstar nullglob
for f in **/*.mp4; do
d=${f%.mp4}
b=$(basename -s.mp4 "$f")
if mkdir -p "$d"; then
ffmpeg -i "$f" -start_number 000 "$d/${b}_%03d.jpg"
else
printf 'could not mkdir %s\n' "$d"
fi
done
Note: for a video named:
videos_1/videos_1_basename_1.mp4
this will create JPEG files named:
videos_1/videos_1_basename_1/videos_1_basename_1_000.jpg
videos_1/videos_1_basename_1/videos_1_basename_1_001.jpg
...
If you really want to keep the .mp4
extension in the names:
videos_1/videos_1_basename_1/videos_1_basename_1.mp4_000.jpg
...
just remove the -s.mp4
option of basename
.
Upvotes: 5
Reputation: 4865
Suggesting to use find
command to get all *.mp4
under current directory.
#!/bin/bash
for currFile in $(find -name "*.mp4"); do
currDir="${currFile %.mp4}"
mkdir -p "$currDir"
ffmpeg -i "$currFile " -start_number 000 "$currDir/${currFile}_%03d.jpg"
done
Upvotes: 1
Reputation: 22225
*.mp4/
would, due to the appended /
, expand to all directories where the name ends in .mp4
. If you don't have directories with such a name, you don't get any wildcard expansion. f
is therefore set to the string *.mp4/
and ${f%.*}
yields a lone *
, as you can try by yourself on the command line. It seems that mkdir
refuses the creation of directory with such a weird name; I would consider this a feature instead of a bug.
There is no recursion in your code with respect to the directories. You could do a
for f in videos_*/*.m4a
inside your parent folder. Of course f
will then also contain the name of the respective subdirectory (for instance videos_1/videos_1_basename_1.m4a
), and you have to adapt your script to this fact.
Upvotes: 0