【问题标题】:Extending a script to loop over multiple files and generate output names扩展脚本以循环多个文件并生成输出名称
【发布时间】:2015-02-18 22:45:57
【问题描述】:

我有以下脚本(名为 vid2gif.sh)将视频文件转换为 gif:

#! /bin/bash
ffmpeg -i $1 /tmp/gif/out%04d.gif
gifsicle --delay=10 --loop /tmp/gif/*.gif > $2

我可以使用命令转换文件:

vid2gif.sh myvid.mp4 myvid.gif

如何才能转换文件夹中的所有 mp4 文件?也就是说,我怎样才能使以下命令起作用:

vid2gif.sh *.mp4

脚本应将文件输出为 *.gif。谢谢你的帮助。

【问题讨论】:

  • 仅供参考,对可执行脚本使用 .sh 扩展名(与打算使用 source 调用的 shell 库相反)是错误的形式——可执行脚本定义命令,而 UNIX 命令没有扩展——它们本质上与语言无关,因为顶部的 shebang 行定义了它们的解释方式。请参阅talisman.org/~erlkonig/documents/… 进行更长时间的讨论。
  • (另外,以#!/bin/bash 开头的脚本是bash 脚本,而不是POSIX sh 脚本,因此使用.sh 扩展名会产生误导;如果使用@987654329 运行,许多此类脚本会以令人惊讶的方式中断@,扩展名意味着支持)。
  • 感谢您的解释。所以我应该将此脚本保存为 vid2gif,将其移动到 /usr/local/bin 文件夹并以“vid2gif”的形式运行。对吗?
  • ...并使用chmod +x 将其标记为可执行,是的。如果您不想为所有用户安装它,而只为您自己安装,您可以考虑创建一个$HOME/bin 目录并将其添加到您的PATH
  • 标题现在的写法——循环遍历文件,而不是参数——更笼统一些,所以我修改了答案的第 (1) 部分以适应。

标签: linux bash shell


【解决方案1】:
#!/bin/sh
for f; do
  tempdir=$(mktemp -t -d gifdir.XXXXXX)
  ffmpeg -i "$f" "$tempdir/out%04d.gif"
  gifsicle --delay=10 --loop "$tempdir"/*.gif >"${f%.*}.gif"
  rm -rf "$tempdir"
done

让我们来看看它是如何工作的:

  1. 迭代

    for f; do
    

    相当于for f in "$@";也就是说,它循环遍历所有命令行参数。相反,如果您想遍历当前目录中的所有 MP4,这将是 for f in *.mp4; do,或者遍历作为第一个命令行参数传递的目录中命名的所有 MP4,它将是 for f in "$1"/*.mp4; do。为了支持这两种用法——但如果没有传递目录,则使用第一个——它将是for f in "${1:-.}"/*.mp4; do

  2. 临时目录使用

    因为原始脚本会为所有内容重用/tmp/gif,所以您会从一个输入源获取文件并在其他输入源中使用。最好通过为每个输入文件创建一个新的临时目录来避免这种情况,mktemp 将自动执行此操作。

  3. 创建.gif 名称

    "${f%.*}" 是一个参数扩展,它删除文件中最后一个. 之后的所有内容;请参阅BashFAQ #100,了解有关 bash 中字符串操作的一般文档,包括这种特殊形式。

    因此,"${f%.*}.gif" 剥离了现有的扩展名,并添加了一个 .gif 扩展名。

【讨论】:

  • 通常在由环境变量TEMPDIR 定义的位置,如果未设置,则为/tmp。请参阅您系统上的 man mktemp 以获取准确的文档。
猜你喜欢
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 2010-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多