为什么在使用sh运行bash代码时失败? [英] Why does my bash code fail when I run it with sh?

查看:307
本文介绍了为什么在使用sh运行bash代码时失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一行代码在我的终端上可以正常工作:

I have a line of code that works fine in my terminal:

for i in *.mp4; do echo ffmpeg -i "$i" "${i/.mp4/.mp3}"; done

然后我将完全相同的代码行放在脚本myscript.sh中:

Then I put the exact same line of code in a script myscript.sh:

#!/bin/sh
for i in *.mp4; do echo ffmpeg -i "$i" "${i/.mp4/.mp3}"; done

但是,现在运行它时出现错误:

However, now I get an error when running it:

$ sh myscript.sh
myscript.sh: 2: myscript.sh: Bad substitution

基于其他问题,我尝试将shebang更改为#!/bin/bash,但得到了完全相同的错误.为什么我不能运行此脚本?

Based on other questions I tried changing the shebang to #!/bin/bash, but I get the exact same error. Why can't I run this script?

推荐答案

TL; DR:由于您使用的是bash特定功能,因此脚本必须使用bash而不是sh运行:

TL;DR: Since you are using bash specific features, your script has to run with bash and not with sh:

$ sh myscript.sh
myscript.sh: 2: myscript.sh: Bad substitution

$ bash myscript.sh
ffmpeg -i bar.mp4 bar.mp3
ffmpeg -i foo.mp4 foo.mp3

请参见 sh和bash之间的区别.要找出正在使用的sh:readlink -f $(which sh).

See Difference between sh and bash. To find out which sh you are using: readlink -f $(which sh).

最佳实践是两者:

  1. #!/bin/sh替换为#!/bin/bash(或脚本所依赖的其他Shell).
  2. 使用./myscript.sh/path/to/myscript.sh运行此脚本(以及其他所有脚本!),而无需前导shbash.
  1. Replace #!/bin/sh with #!/bin/bash (or whichever other shell your script depends on).
  2. Run this script (and all others!) with ./myscript.sh or /path/to/myscript.sh, without a leading sh or bash.

这是一个例子:

$ cat myscript.sh
#!/bin/bash
for i in *.mp4
do
  echo ffmpeg -i "$i" "${i/.mp4/.mp3}"
done

$ chmod +x myscript.sh   # Ensure script is executable

$ ./myscript.sh
ffmpeg -i bar.mp4 bar.mp3
ffmpeg -i foo.mp4 foo.mp3

(相关: shebang建议系统应使用哪个shell运行脚本.这样,您就可以指定#!/usr/bin/python#!/bin/bash,这样您就不必记住哪个脚本是用哪种语言编写的.

The shebang suggests which shell the system should use to run a script. This allows you to specify #!/usr/bin/python or #!/bin/bash so that you don't have to remember which script is written in what language.

当人们仅使用一组有限的功能(由POSIX标准定义)以实现最大的可移植性时,他们会使用#!/bin/sh. #!/bin/bash非常适合利用有用的bash扩展的用户脚本.

People use #!/bin/sh when they only use a limited set of features (defined by the POSIX standard) for maximum portability. #!/bin/bash is perfectly fine for user scripts that take advantage of useful bash extensions.

/bin/sh通常与最小POSIX兼容外壳或标准外壳(例如bash)建立符号链接.即使在后一种情况下,#!/bin/sh也可能会失败,因为bash将以兼容模式运行,如

/bin/sh is usually symlinked to either a minimal POSIX compliant shell or to a standard shell (e.g. bash). Even in the latter case, #!/bin/sh may fail because bash wil run in compatibility mode as explained in the manpage:

如果使用名称sh调用bash,则它会尝试尽可能模仿sh的历史版本的启动行为,同时也要符合POSIX标准.

If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well.

sh myscript.sh

的含义

仅当您运行./myscript.sh/path/to/myscript.sh或放置扩展名,将脚本放在$PATH中的目录中并运行myscript时,才使用shebang.

The meaning of sh myscript.sh

The shebang is only used when you run ./myscript.sh, /path/to/myscript.sh, or when you drop the extension, put the script in a directory in your $PATH, and just run myscript.

如果您明确指定解释器,则将使用该解释器.不管shebang说什么,sh myscript.sh都会强制它与sh一起运行.这就是为什么仅仅改变shebang还是不够的.

If you explicitly specify an interpreter, that interpreter will be used. sh myscript.sh will force it to run with sh, no matter what the shebang says. This is why changing the shebang is not enough by itself.

您应该始终使用脚本的首选解释器运行脚本,因此无论何时执行任何脚本,都首选./myscript.sh或类似脚本.

You should always run the script with its preferred interpreter, so prefer ./myscript.sh or similar whenever you execute any script.

  • It is considered good practice to quote variables ("$i" instead of $i). Quoted variables will prevent problems if the stored file name contains white space characters.
  • I like that you use advanced parameter expansion. I suggest to use "${i%.mp4}.mp3" (instead of "${i/.mp4/.mp3}"), since ${parameter%word} only substitutes at the end (for example a file named foo.mp4.backup).

这篇关于为什么在使用sh运行bash代码时失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆