语法错误:“("意外-在bash脚本中带有!(*.sh) [英] Syntax error: "(" unexpected -- with !(*.sh) in bash script
问题描述
我要运行一个sh文件:
I want to run a sh file:
#!/bin/bash
for f in !(*.sh); do
ffmpeg -i "$f" -vf yadif=0:-1 -threads 0 -c:v libx264 -pix_fmt yuv420p \
-r 29.97 -b:v 3000k -s 1280x720 -preset:v slow -profile:v Main \
-level 3.1 -bf 2 -movflags faststart /mnt/media/out-mp4/"${f%.mxf}.mp4"
rm $f
done
但是,出现以下错误:
2: task1.sh: Syntax error: "(" unexpected
如果我直接在命令行上尝试,它会完美运行.
If I try directly on the command line it works perfectly.
路径和权限已被审核
the path and permissions are already reviewed
你知道会发生什么吗?
推荐答案
这不是"sh文件",而是 bash 脚本.如果使用sh yourscript
运行它,它将无法工作(因为extixlobs,即您要使用的shell功能,在POSIX sh中不受支持);它只需与bash yourscript
一起运行,或者从#!/bin/bash
开始时与./yourscript
一起运行(确实如此).因此,将其描述为"sh文件"会产生误导.而且,即使使用bash,也需要打开扩展的globing功能.
This is not a "sh file" -- it's a bash script. If you run it with sh yourscript
, it will not work (as extglobs, the shell feature you're trying to use, aren't supported in POSIX sh); it needs to be run only with bash yourscript
, or with ./yourscript
when starting with #!/bin/bash
(as it does). Describing it as a "sh file" is thus misleading. Moreover, even with bash, the extended globbing feature needs to be turned on.
您的直接问题是!(*.sh)
不是常规的glob语法;它是 extglob扩展名,默认情况下不可用.您可能具有.bashrc
或类似的配置文件,该文件为交互式shell启用了此扩展名,但不适用于脚本.运行:
Your immediate issue is that !(*.sh)
is not regular glob syntax; it's an extglob extension, not available by default. You may have a .bashrc
or similar configuration file which enables this extension for interactive shells, but that won't apply to scripts. Run:
shopt -s extglob
...启用这些功能.
...to enable these features.
清理后,您的脚本可能如下所示:
Cleaned up, your script might look like:
#!/bin/bash
shopt -s extglob
# putting settings in an array allows unescaped newlines in definition
# also sorted to make it easier to find things.
settings=(
-b:v 3000k
-bf 2
-c:v libx264
-level 3.1
-movflags faststart
-pix_fmt yuv420p
-preset:v slow
-profile:v Main
-r 29.97
-s 1280x720
-threads 0
-vf yadif=0:-1
)
for f in !(*.sh); do
ffmpeg "${settings[@]}" -i "$f" \
/mnt/media/out-mp4/"${f%.mxf}.mp4" && rm -- "$f"
done
请注意除格式之外的以下更改:
Note the following changes, above and beyond formatting:
-
shopt -s extglob
在扩展全局范围之前是自己的行. - 仅在
ffmpeg
成功的情况下运行rm
,因为这些命令之间的分隔符是&&
,而不是;
或裸换行符. - 传递给
rm
的--
参数告诉它将所有以后的参数(在本例中为"$f"
的内容)都视为文件名,即使它以短划线开头也是如此. -
rm
的"$f"
参数在双引号内.
shopt -s extglob
is on its own line, before the glob is expanded.- The
rm
is only run ifffmpeg
succeeds, because the separator between those commands is&&
, rather than either;
or a bare newline. - The
--
argument passed torm
tells it to treat all future arguments (in this case, the content of"$f"
) as a filename, even if it starts with a dash. - The
"$f"
argument torm
is inside double quotes.
这篇关于语法错误:“("意外-在bash脚本中带有!(*.sh)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!