在递归文件夹的批处理脚本中使用 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
我有很多包含 .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