Comment exécuter un script shell sur une console Unix ou un terminal Mac?

507

Je le sais, l'oublie et le réapprends. Il est temps de l'écrire.

Pennsylvanie
la source
15
écrit le train upvote jusqu'à la station de réputation
DivideByZer0
ne va pas voter juste pour admirer cette erreur géniale que vous avez eue!
BRHSM

Réponses:

942

Pour exécuter un shscript non exécutable , utilisez:

sh myscript

Pour exécuter un bashscript non exécutable , utilisez:

bash myscript

Pour démarrer un exécutable (qui est n'importe quel fichier avec une autorisation exécutable); vous le spécifiez simplement par son chemin:

/foo/bar
/bin/bar
./bar

Pour rendre un script exécutable, donnez-lui les autorisations nécessaires:

chmod +x bar
./bar

Lorsqu'un fichier est exécutable, le noyau est responsable de trouver comment l'exécuter. Pour les non binaires, cela se fait en regardant la première ligne du fichier. Il doit contenir hashbang:

#! /usr/bin/env bash

Le hashbang indique au noyau quel programme exécuter (dans ce cas, la commande /usr/bin/envest exécutée avec l'argument bash). Ensuite, le script est transmis au programme (en tant que deuxième argument) avec tous les arguments que vous avez donnés au script comme arguments ultérieurs.

Cela signifie que chaque script exécutable doit avoir un hashbang . Si ce n'est pas le cas, vous ne dites pas au noyau de quoi il s'agit , et donc le noyau ne sait pas quel programme utiliser pour l'interpréter. Il pourrait être bash, perl, python, sh, ou autre chose. (En réalité, le noyau utilise souvent le shell par défaut de l'utilisateur pour interpréter le fichier, ce qui est très dangereux car il pourrait ne pas être du tout le bon interprète ou il pourrait être en mesure d'analyser certains d'entre eux mais avec des différences de comportement subtiles telles que le cas entre shet bash).

Une note sur /usr/bin/env

Le plus souvent, vous verrez une frange de hachage comme ceci:

#!/bin/bash

Le résultat est que le noyau exécutera le programme /bin/bashpour interpréter le script. Malheureusement, il bashn'est pas toujours expédié par défaut et n'est pas toujours disponible en /bin. Alors que sur les machines Linux, c'est généralement le cas, il existe une gamme d'autres machines POSIX livrées bashà divers endroits, tels que /usr/xpg/bin/bashou /usr/local/bin/bash.

Pour écrire un script bash portable, nous ne pouvons donc pas compter sur un codage en dur de l'emplacement du bashprogramme. Posix dispose déjà d' un mécanisme pour faire face à ce qui suit: PATH. L'idée est que vous installez vos programmes dans l'un des répertoires qui s'y trouvent PATHet que le système devrait pouvoir trouver votre programme lorsque vous voulez l'exécuter par son nom.

Malheureusement, vous ne pouvez pas simplement faire ceci:

#!bash

Le noyau ne fera pas (pour certains) une PATHrecherche pour vous. Il existe un programme qui peut faire une PATHrecherche pour vous, cependant, il s'appelle env. Heureusement, presque tous les systèmes ont un envprogramme installé dans /usr/bin. Nous commençons donc à envutiliser un chemin codé en dur, qui effectue ensuite une PATHrecherche bashet l'exécute afin qu'il puisse interpréter votre script:

#!/usr/bin/env bash

Cette approche a un inconvénient: selon POSIX, le hashbang peut avoir un argument . Dans ce cas, nous utilisons bashcomme argument du envprogramme. Cela signifie que nous n'avons plus d'espace pour passer des arguments bash. Il n'y a donc aucun moyen de convertir quelque chose comme #!/bin/bash -exuce schéma. Vous devrez set -exuplutôt mettre le hashbang.

Cette approche a également un autre avantage: certains systèmes peuvent être livrés avec un /bin/bash, mais l'utilisateur peut ne pas l'aimer, peut trouver qu'il est bogué ou obsolète, et peut avoir installé le sien bashailleurs. C'est souvent le cas sur OS X (Mac) où Apple expédie une version obsolète /bin/bashet les utilisateurs installent une mise à jour en /usr/local/bin/bashutilisant quelque chose comme Homebrew. Lorsque vous utilisez l' envapproche qui effectue une PATHrecherche, vous tenez compte des préférences de l'utilisateur et utilisez sa commande préférée par rapport à celle fournie avec son système.

lhunath
la source
66
Merci d'avoir pris le temps d'écrire une bonne réponse à une question simple.
PA
5
Si j'utilise zshcomme coque, utiliserais-je le hashbang #! /usr/bin/env zsh?
stefmikhail
6
@stefmikhail: Peu importe l'interpréteur de shell que vous utilisez pour appeler le script, vous devez utiliser #! /usr/bin/env zshsi (et seulement si) le code à l' intérieur du script doit être exécuté par le shell Z.
Johnsyweb
1
+1 pour explication. j'ai tendance à oublier mais connaître le sens de la commande m'aidera à me souvenir.
Angelin Nadar
2
@Carpetsmoker Ceci est correct et ne se limite pas au hashbang. les scripts bash doivent toujours utiliser des fins de ligne UNIX, sinon le dernier argument de chaque commande sera accompagné d'un \ r, tout comme le nom de la commande hashbang.
lhunath
80

Pour démarrer le shell-script 'file.sh':

sh file.sh

bash file.sh

Une autre option est de définir l'autorisation exécutable à l'aide de la commande chmod:

chmod +x file.sh

Exécutez maintenant le fichier .sh comme suit:

./file.sh
Pennsylvanie
la source
16

Pour la coquille de bourne:

sh myscript.sh

Pour bash:

bash myscript.sh

la source
Merci d'avoir répondu à cette question assez évidente. Pour un Mac comme moi, il est facile d'oublier les anciennes commandes Unix entre les tours.
PA
10

Si vous voulez que le script s'exécute dans le shell actuel (par exemple, vous voulez qu'il puisse affecter votre répertoire ou votre environnement), vous devez dire:

. /path/to/script.sh

ou

source /path/to/script.sh

Notez que cela /path/to/script.shpeut être relatif, par exemple . bin/script.shexécute le script.shdans le binrépertoire sous le répertoire courant.

Chas. Owens
la source
7
Soyez très prudent lorsque vous recherchez ou utilisez des noms de chemins relatifs. Vous devriez toujours les démarrer avec ./ Si vous ne le faites pas et que le chemin d'accès relatif ne contient aucune barre oblique, vous allez chercher quelque chose dans PATH, AVANT quelque chose dans le répertoire courant! Très dangereux pour abus.
lhunath
0

Tout d'abord, autorisez l'exécution: -
chmod +x script_name

  1. Si le script n'est pas exécutable: -
    Pour exécuter le fichier de script sh: -
    sh script_name
    Pour exécuter le fichier de script bash: -
    bash script_name
  2. Si le script est exécutable: -
    ./script_name

REMARQUE : -vous pouvez vérifier si le fichier est exécutable ou non en utilisant 'ls -a'

Vineet Jain
la source
0

L'extension de fichier .command est attribuée à Terminal.app. Double-cliquez sur n'importe quel fichier .command pour l'exécuter.

benwiggy
la source
0

Petit ajout, pour exécuter un interpréteur à partir du même dossier, en utilisant toujours #! Hashbang dans les scripts.

A titre d' exemple un exécutable php7.2 copié à partir de / usr / bin est dans un dossier le long d' un bonjour script.

#!./php7.2
<?php

echo "Hello!"; 

Pour l'exécuter:

./hello

Qui se comportent tout autant que:

./php7.2 hello
NVRM
la source