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

Using mkdir and ffmpeg in a batch script on recursive folders

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

#!/bin/bash
for f in *.mp4; do mkdir -p "${f%.*}" && ffmpeg -i ${f} -start_number 000 "${f%.*}/${f}_%03d.jpg"; done

我可以 运行 对每个父文件夹一次一个,没问题,但我只想 运行 它一次,然后递归地 运行 。

我将代码更改为:

#!/bin/bash
for f in *.mp4/; do mkdir -p "${f%.*}" && ffmpeg -i ${f} -start_number 000 "${f%.*}/${f}_%03d.jpg"; done

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

mkdir: 无法创建目录‘*’: 参数无效

我需要做些什么来让 mkdir 在它们各自的子文件夹中创建适当的新文件夹吗?

文件结构如下:

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

您可以使用 globstar bash 选项在 sub-directories 中递归,也可以使用 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

注意:对于名为:

的视频
videos_1/videos_1_basename_1.mp4

这将创建名为:

的 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
...

如果您真的想在名称中保留 .mp4 扩展名:

videos_1/videos_1_basename_1/videos_1_basename_1.mp4_000.jpg
...

只需删除 basename-s.mp4 选项。

由于附加了 /

*.mp4/ 将扩展到名称以 .mp4 结尾的所有 目录 。如果您没有具有这样名称的目录,则不会得到任何通配符扩展。 f 因此设置为字符串 *.mp4/ 并且 ${f%.*} 产生一个单独的 *,因为您可以在命令行上自己尝试。 mkdir 似乎拒绝创建具有如此奇怪名称的目录;我认为这是一个功能而不是错误。

您的代码中没有关于目录的递归。你可以做一个

for f in videos_*/*.m4a

在您的父文件夹中。当然 f 也将包含相应子目录的名称(例如 videos_1/videos_1_basename_1.m4a),您必须根据这一事实调整您的脚本。

建议使用find命令获取当前目录下的所有*.mp4

#!/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