查找:在名称模式中使用通配符

查找:在名称模式中使用通配符

我有一个简单的包装脚本来播放视频,其中我的脚本尝试查找给定视频文件的字幕文件(如果存在)。给定视频名称,我正在寻找相同的名称,仅以.vtt扩展名结尾而不是视频格式扩展名:

#!/bin/sh

video_file="$1"

sub_file="$(/bin/find -name ${video_file%.*}.*.vtt)"

if [ -f "$sub_file" ] ; then
   echo "subtitles found: $sub_file"
else
   echo "subtitles not found"
fi

如果存在多个子文件,即:foo.en.vtt, foo.de.vtt,我想使用找到的第一个。

问题是上述脚本仅在.vtt存在零个或一个匹配文件时才有效。如果存在两个,则find返回以下错误:

/bin/find: paths must precede expression: `2207-_-20220620.en.vtt'
/bin/find: possible unquoted pattern after predicate `-name'?
subtitles not found

问题似乎是 find 为-name谓词获取了两个参数。但我不能引用该模式,${video_file%.*}.*.vtt因为那样通配符*将被按字面解释。

我尝试使用-regex谓词得到相同的结果

如何在脚本中实现我想要的效果?

答案1

你写了,

但我不能引用该模式,${video_file%.*}.*.vtt因为那样通配符*将被字面解释

我认为在这种情况下这正是你需要做的。引用该字段会阻止 shell 将其作为 glob 应用,但它允许find查看文件名模式中的通配符。 (find -name理解通配符模式本身 - 请参阅man find并搜索解释以-name了解详细信息。)

正如您的问题中所描述的,我们假设视频文件是foo.mp4并且有两个字幕文件foo.de.vttfoo.en.vtt

您可以使用此代码片段来识别这两者

video=foo.mp4
find . -name "${video_file%.*}.*.vtt" -print

这输出

./foo.de.vtt
./foo.en.vtt

您说过您只想要第一个,因此使用非 POSIX 扩展-quit您可以只获取第一个:

subtitles=$(find -name "${video_file%.*}.*.vtt" -print -quit)

echo "> $subtitles"
> ./foo.de.vtt

请注意,find按目录顺序搜索,因此不一定按排序顺序返回结果。如果您可以保证匹配的文件名不包含换行符,您可以find … -print | sort | head -n1根据当前区域设置进行排序。 (然后也是符合 POSIX 标准.)

相关内容