.sh指定扩展名?


12

为什么某些系统.sh仅通过指定不带扩展名的文件名来运行文件,而另一些系统却需要名称加扩展名?就我而言,我正在尝试按照这些说明编写一系列命令。

我现在正在指定扩展名,但是最好能够不运行命令.sh


4
.sh在许多情况下,使用扩展名被认为是不好的做法:与其他命令的命名方式(您不运行ls.elf)相反,它常常会引起误解(如果foo.sh以开头#!/bin/bash,则运行时sh foo.sh将使用与构建时不同的解释器来运行它),并且如果您将其重写foo.sh为Python程序,则使用该扩展名意味着您需要在保留误导性的名称和重写每个调用它的程序之间进行选择。
查尔斯·达菲

2
......它一个最好的做法是壳库,有没有命令+x集-在那里foo.sh是可以采购到任何POSIX外壳库,foo.bash可以将源的bash,foo.ksh进入KSH等
查尔斯·达菲

Answers:


39

你很困惑 该.sh扩展名仅是对人类的提示,对系统处理文件的方式完全没有影响。Unix / Linux并没有使Windows Secrets.pdf.exe大失所望。

这是您输入时发生的事情foo

  1. 重定向STDINSTDOUT以及STDERR是否建立。

  2. Shell检查其内部哈希表以查看是否已经知道的$PATH条目foo。如果不存在,则外壳程序将搜索中的目录$PATH,以查找一个名为foo的文件,该文件的文件许可权中设置了执行位。先foo赢。

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

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

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


15
是的,在Linux上,您可以双击Secrets.pdf,而不会从名称中得知它实际上是可执行文件;)
OrangeDog

1
@OrangeDog我知道你在开玩笑,但是我觉得我必须指出,可执行位(chmod +x)可以解决这个问题,对吗?
wchargin '16

3
@WChargin这取决于文件系统的运行状况(例如,已挂载的网络共享或NTFS分区可能乐观地设置了x所有内容)和文件的来源(可以控制目录控制权的任何进程都可以用来设置权限) 。因此,它可以缓解问题,但我不会说它可以解决问题。
IMSoP '16

2
@WChargin,但是,但我认为他的观点是,文件管理器通常不显示可执行文件位,即没有像扩展程序那样的“对人类的提示”。
Paul Draper

1
我从不会误点击,Secrets.pdf.exe因为我总是禁用愚蠢的hide file extension功能
phuclv '16

12

关键是:扩展与任何类Unix系统都不相关,文件名只是名称,对脚本或编译后的可执行文件是否可以运行没有影响。程序员可以添加.sh扩展名来指定文件是Shell脚本,还是.pypython脚本,但是与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将使脚本被视为键盘输入,即就像直接在命令行中键入一样。在这种情况下,可执行权限和位置无关紧要

例子

Example#1(使用解释器运行)具有执行权限

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

Example#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")

Example#4,具有可执行权限的运行脚本将form文件夹设置为$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

我运行了命令,得到了“ -rwxr-x ---”。我要读取什么值,如何更改它?
菲利普·柯比布里德

还是您说我应该简单地将“ filename.sh”重命名为“ filename”?
菲利普·柯比布莱德

1
@PhilipKirkbride名称无关。您如何运行命令?它在哪里 ?目录是您的一部分PATH吗?
Sergiy Kolodyazhnyy

@PhilipKirkbride让我在一分钟内扩大答案以使其更清楚。
Sergiy Kolodyazhnyy

1
看看man chmod,看看如何设置权限
尼克Mertin

6

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

通常,您需要完成一些相对容易的事情,并从一个小的Shell脚本开始。随着时间的流逝,您开始向脚本中添加越来越多的功能,直到它变得无法维护或者需要一些用shell脚本无法轻松完成的功能,然后考虑用另一种语言重写该shell脚本(python ,perl,...?)。

从头开始重写通常被认为是错误,但是对于脚本来说这可能是有道理的,因为它们通常不大或没有很多功能。但是,让我们假设以某种其他语言从头开始重写,并保持初始shell脚本的功能和params / flags是可行的。

使用此脚本的用户无需了解此语言更改,他们将继续执行相同的命令,它将继续运行。

如果您的脚本被命名为do-something.sh,它可以继续为do-something.sh,但是现在它是用python编写的(例如),因此您的最初提示现在完全是一种误导性提示


4

要运行不带扩展名的文件,您通常不需要做很多事情,只需确保(在bash脚本的情况下)第一行有适当的shebang行:

#!/bin/bash

那么您还需要通过以下方式使文件对系统可执行:

chmod 755 yourfilename

这与使用chmod +x yourfilename数字一样容易解释。

它是添加的八进制的数字三倍,第一个数字代表用户,第二个数字代表组,第三个数字代表其他用户,您可以在这里找到更多信息

而且,如果您与脚本位于同一目录中,请不要忘记使用./以下命令:

./yourfilename

试过这个。不幸的是,与原始结果没有区别。
菲利普·柯比布莱德

@PhilipKirkbride看看我的修改后的答案,这很可能会揭示更多的信息。
Videonauth

0

.sh后缀实际上可能会妨碍您,因为然后运行它,您必须键入myscript.sh而不是仅无法使用myscript。最好不带.sh后缀,将其称为“ myscript”,然后快速使用“ file”命令将告诉您它是二进制可执行文件(在Linux上为ELF格式)还是Shell脚本,或任何其他类型的脚本。

QDOS(Quick and Dirty操作系统,后来在mirosoft盗版并非法出售给他们后,由IBM重命名为“ DOS”)和其他廉价的CP / M盗版,包括Windows,将所有这些混在一起,因为在那些系统上没有例如对文件的执行权限。在过去的30-40年中,这导致了无数的安全问题。其实就在几分钟前,我收到了几封垃圾邮件,它们的诱杀式zip文件重命名为MYPICTURE.JPG.zip :)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.