在递归文件夹的批处理脚本中使用 mkdir 和 ffmpeg

ceb*_*la 1 bash ffmpeg

我有许多包含 .mp4 文件的文件夹。我编写了一个脚本,它获取 mp4 文件并将它们转换为每帧 1 个 jpeg 图像。重要的是,该脚本的输出(保留文件名,末尾附加 _frame 编号)进入一个新创建的文件夹,文件基名如下:

\n
#!/bin/bash\nfor f in *.mp4; do mkdir -p "${f%.*}" && ffmpeg -i ${f} -start_number 000 "${f%.*}/${f}_%03d.jpg"; done\n
Run Code Online (Sandbox Code Playgroud)\n

我可以一次为每个父文件夹运行一个,没有问题,但我想只运行一次并让它递归运行。

\n

我将代码更改为:

\n
#!/bin/bash\nfor f in *.mp4/; do mkdir -p "${f%.*}" && ffmpeg -i ${f} -start_number 000 "${f%.*}/${f}_%03d.jpg"; done\n
Run Code Online (Sandbox Code Playgroud)\n

并尝试使用 mkdir 部分(通过添加 ./),但无论我做什么,我都会收到以下错误。

\n

mkdir:无法创建目录 \xe2\x80\x98*\xe2\x80\x99:参数无效

\n

我需要做什么才能允许 mkdir 在各自的子文件夹中创建适当的新文件夹?

\n

文件结构如下:

\n
parent folder\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 videos_1\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 videos_1_basename_1.mp4\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 videos_2_basename_2.mp4\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 videos_2\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 videos_2_basename_1.mp4\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 videos_2_basename_2.mp4\n.sh script\n
Run Code Online (Sandbox Code Playgroud)\n

Ren*_*let 5

您可以使用globstarbash 选项在子目录中递归,也可以使用该nullglob选项将模式扩展为 null 而不是自身(错误的原因如另一个答案中所述):

#!/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
Run Code Online (Sandbox Code Playgroud)

注意:对于名为:

videos_1/videos_1_basename_1.mp4
Run Code Online (Sandbox Code Playgroud)

这将创建名为:的 JPEG 文件

videos_1/videos_1_basename_1/videos_1_basename_1_000.jpg
videos_1/videos_1_basename_1/videos_1_basename_1_001.jpg
...
Run Code Online (Sandbox Code Playgroud)

如果您确实想将扩展名保留.mp4在名称中:

videos_1/videos_1_basename_1/videos_1_basename_1.mp4_000.jpg
...
Run Code Online (Sandbox Code Playgroud)

只需删除-s.mp4的选项即可basename