【问题标题】:What is the Bash file extension?什么是 Bash 文件扩展名?
【发布时间】:2015-03-04 23:59:39
【问题描述】:

我在文本编辑器中编写了一个 bash 脚本,我应该用什么扩展名保存我的脚本以便它可以作为 bash 脚本运行?我创建了一个理论上应该启动 ssh 服务器的脚本。我想知道单击它后如何使脚本执行。我正在运行 OS X 10.9.5。

【问题讨论】:

  • Shell 脚本不需要任何特定的扩展。只需将其执行为bash myscript
  • 通常是.sh,但扩展名根本不需要存在。 Linux 不是 Windows。解释你的脚本的程序在它的第一行中确定,应该是#!/bin/bash。它甚至可能包含参数。
  • @anubhava 如果我只是双击它而不实际输入“bash myscript”,我将如何让我的脚本执行
  • @Amedeo 将使用 #!/bin/bash 行标题您的文件。

标签: bash shell


【解决方案1】:

您不需要任何扩展名(或者您可以选择任意一个,但.sh 是一个有用的约定)。

你应该以#!/bin/bash 开始你的脚本(第一行被execve(2) 系统调用理解),你应该让你的文件由chmod u+x 执行。因此,如果您的脚本在某个文件 $HOME/somedir/somescriptname.sh 中,您需要输入一次

 chmod u+x  $HOME/somedir/somescriptname.sh

在终端中。命令见chmod(1),系统调用见chmod(2)

除非您输入整个文件路径,否则您应该将该文件放在您的PATH 中提到的某个目录中(请参阅environ(7)execvp(3)),如果您登录,您可以在~/.bashrc 中永久设置该目录外壳是bash)

顺便说一句,您可以用其他语言编写脚本,例如在 Python 中以 #!/usr/bin/python 开头,或者在 Ocaml 中以 #!/usr/bin/ocaml 开头...

通过双击执行脚本(在什么?你没有说!)是desktop environment 问题,可能是特定于桌面的(可能与 Kde、Mate、Gnome、....或 IceWM 或 RatPoison)。也许阅读 EWMH 规范可能会帮助您更好地了解情况。

也许使用chmod 使您的脚本可执行可能会使它在您的桌面上可点击(显然,在MacOSX 上是Quartz)。但是你可能应该让它给出一些视觉反馈。

当您使用ssh 远程访问它时,有几台计算机没有任何桌面,包括您自己的。

我认为通过单击运行您的 shell 脚本不是一个好主意。您可能希望能够为您的 shell 脚本提供参数(以及如何通过单击来做到这一点?),并且您应该关心它的输出。如果您能够编写 shell 脚本,则可以在终端中使用交互式 shell。这是使用脚本的最佳和最自然的方式。良好的交互式 shell(例如 zshfish 或者最近的 bash)具有美味且可配置的 autocompletion 设施,您不必输入很多内容(学习使用 tab 键盘的键)。此外,脚本和程序通常是复合命令(管道等)的一部分。

PS。我从 1986 年开始使用 Unix,从 1993 年开始使用 Linux。我从来没有通过单击来启动自己的程序或脚本。我为什么要?

【讨论】:

  • 好的,我已经在文本编辑器中创建了我的脚本。我将文件保存到我的桌面。当我单击保存在桌面上的脚本时,我希望它在我单击它时实际运行。
  • 我不知道你的桌面是什么(KDE、Gnome、MATE,...)。我强烈邀请您在终端中使用命令行,尤其是运行您的脚本(您可能想给它们一些参数;您将如何在桌面上执行此操作?)。如果你能够编写一个 shell 脚本,你应该能够在终端中以交互方式使用 shell
  • 我的观点是,如果你正在编写一个 shell 脚本,你应该养成在终端中使用命令行的习惯。
  • 我明白,这是我正在工作的项目。我希望脚本在单击后执行。我试图避免使用终端来运行脚本。
  • 我会使用 chmod +x 而不是 chmod u+x,除非有特定原因限制所有者的可执行性。
【解决方案2】:

TL;DR -- 如果脚本的用户(不一定是开发人员)使用 GUI 界面,这取决于他们使用的文件浏览器。 MacOS 的 Finder 需要 .sh 扩展名才能执行脚本。然而,Gnome Nautilus 可以识别带有或不带有 .sh 扩展名的正确 shebanged 脚本。

我知道支持和反对在 bash 脚本上使用扩展的原因已经被多次提及,但没有那么多为什么或为什么不使用扩展,但我有一个我认为是好的经验法则。

如果您是那种跳进跳出 bash 并通常使用终端的类型,或者正在为不使用终端的其他人开发工具,请在您的 bash 脚本中添加 .sh 扩展名。这样,该脚本的用户可以选择在 GUI 文件浏览器中双击该文件来运行该脚本。

如果您是主要在终端中完成所有或大部分工作的类型,请不要费心在您的 bash 脚本上添加任何扩展。假设您已经设置了 ~/.bashrc 文件以在视觉上区分脚本和目录,那么它们在终端中没有任何作用。

编辑:

在带有 4 个测试文件的 Gnome Nautilus 文件浏览器中(每个测试文件都具有要执行的文件的权限),使用简单的 bash 命令打开终端窗口 (gnome-terminal):

  1. 一个没有扩展名的文件,第一行带有#!/bin/bash

    双击文件就可以了。

  2. 带有.sh 扩展名的文件,第一行带有#!/bin/bash

    双击文件就可以了。

  3. 一个没有扩展名的文件,第一行没有#!/bin/bash

    它通过双击文件来工作...从技术上讲,但 GUI 没有表明它是一个 shell 脚本。它说它只是一个纯文本文件。

  4. 带有.sh 扩展名的文件,第一行没有#!/bin/bash

    双击文件就可以了。

但是,正如 Keith Thompson 在此答案的 cmets 中明智地指出的那样,依靠使用 .sh 扩展名而不是文件第一行 (#!/bin/bash) 上的 bash shebang 可能会导致问题.

然而,我记得当我以前使用 MacOS 时,即使没有 .sh 扩展名的正确 shebanged(这是一个词?)bash 脚本也无法从 MacOS 上的 GUI 运行。不过,我希望有人能在 cmets 中纠正我的问题。如果这是真的,这将证明至少有一个文件浏览器在其中.sh 扩展名很重要。

【讨论】:

  • 您使用哪个 GUI 文件浏览器(或者,更相关的是,您的用户使用什么)?它是否使用扩展来决定如何运行脚本?
  • 嗯,我最有经验的平台是MacOS。在 Finder 中,用户决定哪些应用与哪些扩展相关联。现在,我在 Linux 上使用 Gnome,但我还没有开始尝试 Gnome 的 Nautilus 文件浏览器如何与没有扩展名的文件交互。
  • 如果你有一个第一行带有.sh 后缀和#!/bin/bash 的可执行脚本,GUI 文件浏览器是否会使用sh 来调用它(忽略shebang)?如果是这样,那可能会导致一些问题。 (不同浏览器的答案可能不同。)
  • 好点。我已经用我刚才做的一些实际测试更新了我上面的答案。
  • 有趣,但是……你说它“有效”。对于 4 个测试用例中的每一个,最好知道它是使用 /bin/bash 还是 /bin/sh 调用它(后者是没有 shebang 的脚本的默认值)。如果/bin/sh/bin/bash 的符号链接(这很常见),那么您可以通过查看$0 的值来判断。 (另外,如果 bash 被调用为 sh,它会设置为 POSIXLY_CORRECT=y。)
【解决方案3】:

不同意其他答案,有一个通用约定为 shell 脚本使用 .sh 扩展名——但这不是一个有用的约定。最好不要使用扩展。能够判断foo.sh 是一个shell 脚本的好处是最小的,因为它的名称是最小的,并且您为此付出代价却失去了灵活性。

要使 bash 脚本可执行,它需要在顶部有一个 shebang 行:

#!/bin/bash

并使用chmod +x 命令,以便系统将其识别为可执行文件。然后需要将其安装在$PATH 中列出的目录之一中。如果脚本名为foo,则可以在shell 提示符下键入foo 来执行它。或者如果它在当前目录中(临时脚本常用),您可以输入./foo

shell 和操作系统都不注意文件名的扩展部分。这只是名字的一部分。通过给它一个特殊的扩展,你可以确保使用它的任何人(无论是用户还是其他脚本)都不必关心它是如何实现的,无论它是一个 shell 脚本(sh, bash、csh 或其他)、Perl、Python 或 Awk 脚本或二进制可执行文件。该系统经过专门设计,可以调用解释脚本或二进制可执行文件,而无需知道或关心它是如何实现的。

类 UNIX 系统开始于纯文本命令行界面。后来添加了 KDE 和 Gnome 等 GUI。在 GUI 桌面系统中,您通常可以通过例如双击引用它的图标来运行程序(同样,无论是脚本还是二进制可执行文件)。通常,这会丢弃程序可能打印的任何输出,并且不允许您传递命令行参数;它远不如从 shell 提示符下运行灵活。但对于某些程序(主要是 GUI 客户端)来说,它会更方便。

最好从命令行学习 Shell 脚本,而不是从 GUI。

(某些工具确实注意文件扩展名。例如,编译器通常使用扩展名来确定编写代码的语言:.c 用于 C,.cpp 用于 C++,等等。此约定不适用于可执行文件。)

请记住,UNIX(和类似 UNIX 的系统)不是 Windows。 MS Windows 通常使用文件的扩展名来确定如何打开/执行它。二进制可执行文件需要有一个.exe 扩展名。如果你在 Windows 下安装了类 UNIX 的 shell,你可以配置 Windows 将.sh 扩展识别为 shell 脚本,并使用 shell 打开它; Windows 没有#! 约定。

【讨论】:

  • 我的目标是你在第四段中提到的。单击引用它的图标时运行我的脚本。
  • @Amedeo:那要看你的桌面环境了。在我使用的那个(Ubuntu下的Cinnamon)中,双击可执行脚本的图标会提示我在终端中运行它,在编辑器中显示它,或者在没有终端的情况下运行它。无论文件扩展名如何,它都会这样做。
  • (Necro) 如果省略扩展名,则无法拥有同名文件夹。因此,例如,您有deploy.sh(或deploy.bash)和一个文件夹deploy,以及额外的部署逻辑。如果您将脚本重命名为简单的deploy,则会导致名称冲突。以不同方式命名文件或文件夹会损害可管理性并可能会损害文件排序(ls,在编辑器中等)。当然,shebang 最终是决定因素。但文件扩展名确实有其应有的地位。
  • @Kafoso:我认为我从来没有觉得需要拥有同名的脚本和目录。如果我这样做了,我可能会调用目录Deploy,尽管这可能会在复制到不区分大小写的文件系统时导致问题。
  • 在 Mac 上,双击文件总是会在默认应用中打开它们。因此,拥有.sh 扩展名会很有帮助,这样脚本就可以在您想要的编辑器中打开。如果你想在双击时运行一个脚本,给它.command扩展名,它会在双击时在终端中运行。
【解决方案4】:

我知道这已经很老了,但我觉得这增加了问题的要求。

如果您在 Mac 上并且希望能够通过双击来运行脚本,则需要使用 .command 扩展名。也与之前使用chmod -x 使文件可执行。

如前所述,这并没有那么有用。

【讨论】:

    【解决方案5】:

    只需.sh

    像这样运行脚本:

    ./script.sh
    

    编辑:就像 anubhava 所说,扩展并不重要。但出于组织原因,仍建议使用扩展。

    【讨论】:

    • 如果你正在运行一个脚本,你通常没有理由关心它是用什么写的。bash 脚本和二进制可执行文件的执行方式相同。在可执行脚本中添加.sh 后缀通常是无用的混乱。
    • 是的,但正如我在编辑中所说 - 这是组织脚本的惯例 - 不是更多?!
    • 我确实看到很多带有.sh 扩展名的脚本(而带有.bash 扩展名的脚本更少),但我不相信它完全有用。如果我将一个脚本命名为foo.sh,然后我决定在 Perl 中重新实现它,我可以更改名称(并编辑使用它的所有内容),或者保留一个误导性的扩展名。如果我把它命名为foo,我就没有这个问题。
    • @KeithThompson 我自己能想到一个用途,我确实关心脚本是用什么写的。我不能代表 Perl,但我会非常关心是否脚本是用 Python 或 Bash 编写的。我通常可以假设 Bash 脚本无论如何都可以工作,但是 Python 脚本具有依赖关系,并且 Python 2 和 Python 3 彼此不兼容。我还认为区分已编译的二进制文件和脚本(它们都没有扩展名)很重要,因为它们有不同的依赖需求(例如,二进制文件可能需要库并针对 AMD64 进行编译,并且只能在此基础上工作)。
    • @jrh 当然,有时它很重要(您可以通过运行head -1 script.foofile script.foo 来判断)。但是,如果一切都安装和配置正确,99% 的时间我只希望命令执行它应该执行的操作。对我来说,这并不能证明每次运行时都必须知道 .py.bash 后缀。
    猜你喜欢
    • 2010-09-08
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 2019-03-26
    • 2012-01-03
    相关资源
    最近更新 更多