.sh 指定扩展名?

.sh 指定扩展名?

为什么有些系统.sh只需指定文件名而不指定扩展名即可运行文件,而其他系统则需要名称加扩展名? 就我而言,我尝试按照这些命令编写一系列命令指示

我现在正在指定扩展,但如果能够在没有扩展的情况下运行命令.sh就更好了。

答案1

您搞糊涂了。.sh扩展名只是对人类的一个提示,对系统处理文件的方式完全没有影响。Unix/Linux 没有犯下 Windows 的Secrets.pdf.exe错误。

当您输入以下内容时,将发生以下情况foo

  1. 已设置 STDINSTDOUT和的重定向。STDERR

  2. shell 检查其内部哈希表,查看是否已经知道 的$PATH条目foo。如果不存在,shell 会搜索 中的目录$PATH,查找名为 且foo在其文件权限中设置了执行位的文件。先到foo先得。

  3. 如果文件的前两个字节foo#!,则下一个字符串是要运行的解释器的名称。因此#!/bin/bash引入了一个 Bash 脚本,#!/usr/bin/perl引入了一个 Perl 脚本,等等。

  4. 如果文件以 开头\177ELF,则它是二进制可执行文件,并ld.so启动它。

阅读man execveman ld.so获得更详细的解释。

答案2

关键点是这样的:扩展名在任何类 Unix 系统中都是无关紧要的。文件名只是名称,对脚本或编译后的可执行文件是否可以运行没有影响。程序员可以添加.sh扩展名来表明某个文件是 shell 脚本,或者.py是 python 脚本,但与 Windows 不同,任何 unix 都不关心命名,它只关心权限。

重要的是授予文件的可执行权限。您可以使用以下命令进行检查

ls -l /path/to/file

运行可执行文件

运行脚本一般有几种方法。

  • 如果您的当前目录与脚本相同,并且脚本具有可执行权限,则可以像这样运行它./my_script_name.表示当前目录。
  • 如果您的当前目录不同并且脚本具有可执行权限,则可以通过指定完整路径来运行它:/home/user/bin/my_script_name

(以上两种方法依赖于设置可执行权限;文件是否是$PATH变量的一部分无关紧要。#!行的存在也很重要;如果没有它,脚本将由您打开的当前 shell 执行。如果我的csh脚本没有该行,并尝试在 bash 中使用运行它./my_script.csh,它将失败)

  • 如果您的脚本位于属于$PATH变量的目录中,则只需调用名称即可运行它。您chmod只需在命令行中输入其名称即可调用命令,因为它位于/bin文件夹中。/bin始终是$PATH变量的一部分。在这种情况下,可执行权限和脚本的位置很重要
  • 指定解释器作为命令,脚本作为参数。这样,​​脚本将作为解释器的输入文件。
  • 获取文件。. filename.shsource filename.sh将使脚本被视为键盘输入,即直接输入命令行。在这种情况下,可执行权限和位置无关紧要

例子

示例 #1,使用解释器运行,以执行权限

$-> ls -l abc.py                                                               
-rw-rw-r-- 1 xieerqi xieerqi 44 Apr 27 22:39 abc.py
$-> python abc.py                                                              
a
b
c

示例#2,使用./可执行权限集和shebang 行集运行。

$-> cat abc.py                                                                 
#!/usr/bin/env python
for letter in 'a' 'b' 'c' :
   print letter
$-> ls -l abc.py
-rwxrwxr-x 1 xieerqi xieerqi 66 Apr 27 23:02 abc.py*
$-> ./abc.py                                                                   
a
b
c

示例 #3,未设置 shebang 行的情况下运行(失败,因为 bash 无法读取 python 脚本;没有 shebang 行假定当前 shell 作为解释器)

$-> cat abc.py                                                                 
for letter in 'a' 'b' 'c' :
   print letter
$-> ./abc.py                                                                   
./abc.py: 2: ./abc.py: Syntax error: word unexpected (expecting "do")

示例 #4,运行具有可执行权限的脚本,该权限设置来自$PATH变量的一部分文件夹

#  /home/xieerqi/bin is part of my path variable
$-> echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/microchip/xc16/v1.25/bin:/opt/microchip/xc32/v1.40/bin:/opt/microchip/xc8/v1.35/bin:/home/xieerqi/bin:/home/xieerqi/bin/sh

$-> # current directory is /home/xieerqi
$-> pwd
/home/xieerqi
$-> # move the file to ~/bin
$-> mv ~/abc.py ~/bin/abc.py
$-> # now I can run it just by calling the name
$-> abc.py
/home/xieerqi/bin/abc.py: 2: /home/xieerqi/bin/abc.py: Syntax error: word unexpected (expecting "do")
$-> # Syntax error because again, no interpreter specified.                    
$-> # must add #!/usr/bin/env python
$-> vi /home/xieerqi/bin/abc.py          
$-> # after adding the line with vi text editor, we can run
$-> abc.py                                                                     
a
b
c

示例#5,删除扩展,仍然可以运行,因为扩展并不重要,但它具有权限并且是其中的一部分$PATH

$-> mv ~/bin/abc.py  ~/bin/abc                                                 
$-> abc
a
b
c

答案3

这里已经有很好的解释。我只是想补充一点,理想情况下你不应该对可执行文件使用文件扩展名。

通常你需要完成一些相对简单的事情,并且从一个小的 shell 脚本开始。随着时间的推移,你开始向脚本添加越来越多的功能,直到它变得无法维护,或者你需要一些无法用 shell 脚本轻松实现的功能,并考虑用另一种语言(python、perl 等?)重写这个 shell 脚本。

从头重写通常被认为是一种错误,但对于脚本来说,这可能是有意义的,因为它们通常不是那么大或具有很多功能。但让我们假设用其他语言从头重写是可行的,同时保留初始 shell 脚本的功能和参数/标志。

该脚本的用户不需要了解这种语言变化,他们将继续执行相同的命令,并且它将继续工作。

如果你的脚本被命名为do-something.sh,它可以继续存在do-something.sh,但现在它是用python编写的(例如),所以你的初始暗示现在却完全是误导性的。

答案4

.sh 后缀实际上会造成问题,因为要运行它,您必须键入 myscript.sh,而不是只键入 myscript,因为这样是行不通的。最好直接将其命名为“myscript”,而不使用 .sh 后缀,然后快速使用“file”命令即可知道它是二进制可执行文件(Linux 上的 ELF 格式)还是 shell 脚本,或者任何其他类型的脚本。

QDOS(Quick and Dirty 操作系统,后来被 IBM 更名为“DOS”,因为微软盗版并非法将其出售给他们)和其他廉价的 CP/M 仿制品,包括 Windows,将所有这些都混为一谈,因为在这些系统上没有文件执行权限。这在过去 30-40 年里导致了无数的安全问题。实际上,就在几分钟前,我收到了几封垃圾邮件,里面有一个被重命名为 MYPICTURE.JPG.zip 的陷阱 zip 文件 :)

相关内容