![查找:在名称模式中使用通配符](https://linux22.com/image/211889/%E6%9F%A5%E6%89%BE%EF%BC%9A%E5%9C%A8%E5%90%8D%E7%A7%B0%E6%A8%A1%E5%BC%8F%E4%B8%AD%E4%BD%BF%E7%94%A8%E9%80%9A%E9%85%8D%E7%AC%A6.png)
我有一个简单的包装脚本来播放视频,其中我的脚本尝试查找给定视频文件的字幕文件(如果存在)。给定视频名称,我正在寻找相同的名称,仅以.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.vtt
和foo.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 标准.)