我有这个在 Windows 中使用的批处理文件,我想将其转换为 Linux 脚本。有人能帮忙吗?这是脚本和 Linux 版本的尝试。这不是我写的,是有人帮助我的。
目的是运行一个 Python 命令“manual.py”,该命令使用 FFmpeg 将任何非 MP4 文件转换为 MP4。我已将其作为计划任务在 Windows 中针对映射的 Linux 共享运行;但是,我宁愿让脚本在 Linux 机器上运行。我的 Linux 脚本技能,嗯,不存在。
这有效
@echo off
setlocal enableDelayedExpansion
Set Location="z:\movies"
Set PatternName=".*\.mp4 .*\srt"
Set Transcoder="c:\sysinternals\mp4auto\"
for /f "delims=" %%F in ('dir %Location% /s /b /a-d ^| findstr /v /i /e /r %PatternName%') do (%Transcoder%manual.py -i "%%F" -a
)
这不。
!#/bin/sh
Location="/TV Shows/*/*"
Pattern="*.mp4"
Transcode = /Mp4auto/manual.py
for Convert in (find $Location -type f \( -iname "*.*" ! -iname $Pattern \))
do
$Transcode -i $Convert -a
done
我需要做什么才能让它工作?
答案1
有几个问题:
- Shell 脚本的前两个字符应该是
#!
, 而不是!#
。
假设您选择使用 POSIX 类型的 shell(这是一个不错的选择):
- 分配给变量时, 之前或之后不能有空格
=
。 - 当你使用(參考) 变量,您几乎总是应该将其放在引号中。(我们经常说,除非您有充分的理由不这样做,否则您应该始终引用 shell 变量,并且您当然你知道你在做什么。
- 您正在运行该
find
命令,并获取其输出并将其用作更大命令的一部分。您将该find
命令放在括号中。您需要将其放入$(
…)
。 - 但这不是一种好方法,如果任何路径名包含空格,就会失败。所以它会飞得很高,因为全部您的路径名将包含空格,因为您的目录名是
"/TV Shows"
。
我会回过头来谈这个问题。
- 的第一个参数
find
通常应该是目录的名称。这是一个过于简单的说法 — 有很多变体 — 但重点是您应该给出find
一个参数"/TV Shows"
。您不需要指定"/TV Shows/*/*"
;find
将查找"/TV Shows"
目录下的所有文件。 - 如果您只想查看两级目录,请这么说。
其他说明:
您的 BAT 文件使用了该
.*\srt
模式。但您没有解释这一点的重要性,也没有尝试将其翻译成您的 shell 脚本。您可以在 shell 脚本中使用命令。这将匹配所有
-iname "*.*"
文件find
有一个.
名称中没有句点。(这个字符称为“句号”、“句号”和“点”)。并非所有 Unix 文件的名称中都有句点,因此这与匹配所有文件不同。如果您想排除名称中没有点的文件,这是正确的做法。我指出这一点是因为从 Windows 过渡过来的人们习惯于认为这
*.*
意味着所有文件。Unix 新手(
find
尤其是)有时认为他们需要说-name "*"
或类似的话来获取所有文件,然后开始指定排除项。这是不必要的;find
发现全部默认文件。您没有指定排除名称中没有点的文件的要求。
脚本流程全部名称中带有点且不以 结尾的文件
.mp4
。这可能包括.py
文件、.txt
文件等。搜索可以转换为 MP4 的文件类型可能更安全。
因此,如果您愿意将您的目录重命名为TV_Shows
,并且可以保证您的文件名都不包含空格,那么这应该可以帮助您入门:
#!/bin/sh
Location="/TV_Shows"
Pattern="*.mp4"
Transcode=/Mp4auto/manual.py
for Convert in $(find "$Location" -type f \( -iname "*.*" ! -iname "$Pattern" \))
do
"$Transcode" -i "$Convert" -a
done
处理包含空格的路径名的更好的方法是使用find
对找到的每个文件运行命令的功能:
#!/bin/sh
Location="/TV Shows"
Pattern="*.mp4"
Transcode=/Mp4auto/manual.py
find "$Location" -type f \( -iname "*.*" ! -iname "$Pattern" \) -exec "$Transcode" -i {} -a ';'
您可以使用\
(反斜杠)将该长命令拆分为两行:
find "$Location" -type f \( -iname "*.*" ! -iname "$Pattern" \) \
-exec "$Transcode" -i {} -a ';'
我刚刚注意到原帖者问了一个后续问题:
你能给我举个例子,如何转换任何以 .mkv 或 .avi 为扩展名的文件吗?
在 中使用-o
,表示“或” find
:
︙
Pattern1="*.mkv"
Pattern2="*.avi"
︙
find "$Location" -type f \( -iname "$Pattern1" -o -iname "$Pattern2" \) \
-exec "$Transcode" -i {} -a ';'