J'ai créé un programme C simple comme ceci:
int main(int argc, char *argv[]) {
if (argc != 5) {
fputs("Not enough arguments!\n", stderr);
exit(EXIT_FAILURE);
}
Et j'ai mon PATH modifié dans etc / bash.bashrc comme ceci:
PATH=.:$PATH
J'ai enregistré ce programme en tant que set.c et je le compile avec
gcc -o set set.c
dans le dossier
~/Programming/so
Cependant, quand j'appelle
set 2 3
il ne se passe rien. Aucun texte n'apparaît.
Appel
./set 2 3
donne le résultat attendu
Je n'ai jamais eu de problème avec PATH auparavant et
which set
retourne ./set
. Il semble donc que le CHEMIN soit le bon. Que se passe-t-il?
shell
path
shell-builtin
Ganea Dan Andrei
la source
la source
test
pour essentiellement la même raison;test
est également un shell intégré.test
semble logique. Bien sûr, au moment où vous le mettez dans votre,PATH
vous devriez vraiment avoir trouvé un nom différent. Et jusqu'à ce que vous mettiez le programme dans votre,PATH
vous devrez l'invoquer comme de./test
toute façon. Il est donctest
assez correct d'utiliser le nom d'un programme tant qu'il s'agit d'un test rapide que vous avez l'intention de supprimer avant la fin de la journée.foo
.ls
chaque fois que vous allez voir s'il existe, il s'exécutera (mais uniquement si vous modifiez votre chemin comme vous l'avez fait dans la question).Réponses:
Au lieu d'utiliser
which
, qui ne fonctionne pas lorsque vous en avez le plus besoin , utiliseztype
pour déterminer ce qui va s'exécuter lorsque vous tapez une commande:Le shell recherche toujours les commandes internes avant de rechercher le
$PATH
, donc le réglage$PATH
n'aide pas ici.Il serait préférable de renommer votre exécutable en quelque chose d'autre, mais si votre affectation nécessite que le programme soit nommé
set
, vous pouvez utiliser une fonction shell:(Cela fonctionne
bash
, mais d'autres shells commeksh
ne le permettent pas. Voir la réponse de mikeserv pour une solution plus portable.)Maintenant, la frappe
set
exécutera la fonction nommée "set", qui s'exécute./set
. GNUbash
recherche des fonctions avant de rechercher des commandes internes, et il recherche des commandes internes avant de rechercher le$PATH
. La section nommée "EXÉCUTION DE COMMANDE" dans la page de manuel bash donne plus d'informations à ce sujet.Voir aussi la documentation sur
builtin
etcommand
:help builtin
ethelp command
.la source
type
pluswhich
, mais n'en donnez aucune raison. ( Je sais pourquoi , mais quelqu'un qui a besoin de la recommandation ne le ferait pas.)type
place dewhich
, ne nommez pas votre programme "set", et réalisez quefunction set { ./set; }
c'est un vilain hack que vous devriez probablement éviter.set
est une fonction intégrée dans bash (et probablement la plupart des autres coquilles). Cela signifie que bash ne cherchera même pas le chemin lors de la recherche de la fonction.Comme remarque secondaire, je déconseille fortement d'ajouter
.
au chemin pour des raisons de sécurité. Imaginez, par exemplecd
,/tmp
qu'après qu'un autre utilisateur ait ajouté un fichier exécutable/tmp/cd
.la source
cd
est un shell intégré, donc l'exemple ne fonctionnera pas pour la même raison qu'avecset
../foo
pour invoquer un programme est professionnel; cela montre que vous comprenez pourquoi.
ne pas être dans $ PATH. Votre professeur a tort et vous pouvez lui dire que je l'ai dit.set
n'est pas seulement une fonction intégrée, c'est une fonction spéciale POSIX . Il y a quelques commandes prédéfinies qui sont des normes spécifiées à trouver dans une recherche de commande avant toute autre chose -$PATH
, les noms de fonctions ne sont pas recherchées ne sont pas fouillés, etc La plupart des fonctions intégrées qui sont pas spéciaux sont effectivement nécessaires par la norme POSIX pour être trouvé dans votre$PATH
avant que le shell n'exécute l'une de ses propres procédures internes. Ceci est vraiecho
et la plupart des autres (bien que si la norme est honorée à cet égard a été une question de discorde dans les listes de diffusion de groupe ouvert dans le passé) , mais pas deset
,trap
,break
,return
,continue
,.
,:
,times
,eval
,exit
,export
,readonly
,unset
Ouexec
.Tous ces noms sont réservés au shell, et ils ont également des attributs spéciaux autres que leur ordre de préférence pour la recherche de commandes. Par exemple, vous ne pouvez pas définir une fonction shell avec l'un de ces noms dans un shell conforme aux normes. C'est une bonne chose - cela permet aux gens d'écrire des scripts portables en toute sécurité . Ce sont des commandes de base à partir desquelles un scénariste expérimenté peut établir une position sûre et fiable dans son environnement. Il n'est pas conseillé d' envahir cet espace de noms .
Cependant, si vous souhaitez l'envahir, vous pouvez le faire de manière portable avec
alias
. L'ordre d' expansion du shell permet ce contournement. Étant donné que lealias
est développé pendant la lecture de la commande, tout ce que vous remplacez par leset
nom dans votre définition se développera correctement, il ne devrait probablement pas s'étendre à l'un de ces noms.Vous pourriez donc faire:
... qui fonctionnera très bien.
la source
Le problème est qu'il
set
s'agit d'un shell intégré et la meilleure solution serait d' utiliser un nom différent pour votre programme exécutable.Soit dit en passant , la semaine dernière, j'ai posé une question sur la façon d' exécuter des commandes système au lieu des commandes internes du même nom et la solution que j'ai acceptée a été d'exécuter la commande via
env
:Pour ce cas particulier, où vous savez déjà que la commande que vous souhaitez utiliser se trouve dans votre répertoire courant, il serait préférable d'exécuter directement l'exécutable en entrant son chemin (en utilisant
.
pour représenter le répertoire de travail courant):Les deux solutions ci-dessus sont indépendantes du shell, c'est-à-dire qu'elles fonctionneront quel que soit le shell que vous utilisez.
Des suggestions telles que l'utilisation de la fonction
command
intégrée ne fonctionneront pas dans Bash: cela empêche uniquement l' exécution des fonctions shell . Bien que cela ne soit pas documenté, j'ai également remarqué que l'utilisationcommand
supprime également les mots clés du shell . Cependant, cela ne fera pas de même pour les commandes internes telles queset
. Si je comprends bien,command
peut fonctionner avec d'autres shells tels que zsh.De plus, des astuces telles que
\set
ou"set"
ou'set'
ne fonctionnent pas pour les builds Bash - bien qu'elles soient utiles pour exécuter des fichiers exécutables au lieu d' alias ou de mots clés shell .Remarque: Cette réponse a commencé à l'origine comme un commentaire sur la réponse (acceptée) d'Eric, mais elle est devenue trop grande pour tenir dans un commentaire. Les autres réponses recommandant d'utiliser
type
et de ne pas ajouter.
au CHEMIN sont bonnes.la source