gpt4 book ai didi

bash - 当我使用 'sh' 运行 Bash 代码时,为什么它会失败?

转载 作者:太空宇宙 更新时间:2023-11-04 11:48:58 25 4
gpt4 key购买 nike

我有一行代码在我的终端中运行良好:

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

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

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

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

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

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

最佳答案

TL;DR:由于您使用的是 Bash 特定功能,因此您的脚本必须使用 Bash 而不是 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

参见 Difference between sh and Bash 。要找出您正在使用哪个 sh:readlink -f $(which sh)

确保 bash 特定脚本始终正确运行的最佳方法

最佳做法是两者:

  1. #!/bin/sh 替换为 #!/bin/bash(或您的脚本所依赖的任何其他 shell)。
  2. 使用 ./myscript.sh/path/to/myscript.sh 运行此脚本(以及所有其他脚本!),没有前导 shbash

这是一个例子:

$ 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

(相关:Why ./ in front of scripts?)

#!/bin/sh的含义

shebang 建议系统应该使用哪个 shell 来运行脚本。这允许您指定 #!/usr/bin/python#!/bin/bash 这样您就不必记住哪个脚本是用什么语言编写的.

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

/bin/sh 通常符号链接(symbolic link)到最小的 POSIX 兼容 shell 或标准 shell(例如 bash)。即使在后一种情况下,#!/bin/sh 也可能会失败,因为 bash 将以兼容模式运行,如 man page 中所述。 :

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的含义

shebang 仅在运行 ./myscript.sh/path/to/myscript.sh 时使用,或者当您删除扩展名时,将脚本放入在您的 $PATH 目录中,然后运行 ​​myscript

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

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

对脚本的其他建议更改:

  • 引用变量("$i" 而不是 $i)被认为是好的做法。如果存储的文件名包含空格字符,带引号的变量将防止出现问题。
  • 我喜欢你使用高级 parameter expansion .我建议使用 "${i%.mp4}.mp3"(而不是 "${i/.mp4/.mp3}"),因为 ${parameter%word} 仅在末尾替换(例如名为 foo.mp4.backup 的文件)。

关于bash - 当我使用 'sh' 运行 Bash 代码时,为什么它会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56672990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com