Pourquoi " cd " ne fonctionne pas dans un script shell?
j'essaie d'écrire un petit script pour changer le répertoire courant de mon répertoire de projet:
#!/bin/bash
cd /home/tree/projects/java
j'ai enregistré ce fichier en tant que proj, j'ai ajouté la permission d'exécuter avec chmod
, et je l'ai copié sur /usr/bin
. Quand je l'appelle par:
proj
, ça ne fait rien. Ce que je fais mal?
29 réponses
sont exécutés à l'intérieur d'une sous-couche, et chaque sous-couche a son propre concept de ce qu'est le répertoire courant. Le cd
réussit, mais dès que le subshell sort, vous êtes de retour dans le shell interactif et rien n'y a jamais changé.
une façon de contourner ceci est d'utiliser un alias à la place:
alias proj="cd /home/tree/projects/java"
vous ne faites rien de mal! Vous avez changé le répertoire, mais seulement dans la sous-couche qui exécute le script.
vous pouvez exécuter le script dans votre processus actuel avec la commande" dot":
. proj
mais je préfère la suggestion de Greg d'utiliser un alias dans ce cas simple.
le cd
dans votre script techniquement a fonctionné car il a changé le répertoire de l'interpréteur de commandes qui exécutait le script, mais c'était un processus séparé bifurqué de votre interpréteur de commandes interactif.
une façon compatible avec Posix pour résoudre ce problème est de définir une procédure shell plutôt qu'un script de commande invoqué par shell .
jhome () {
cd /home/tree/projects/java
}
vous pouvez taper ou le mettre dans l'un des divers shell fichiers de démarrage.
le cd
est fait dans le shell du script. Quand le script se termine, ce shell sort, Et alors vous êtes laissé dans le répertoire que vous étiez. "Source" le script, ne le lance pas. Au lieu de:
./myscript.sh
faire
. ./myscript.sh
(Notez le point et l'espace avant le nom du script.)
pour faire un script bash qui cd dans un répertoire select:
créer le fichier de script
#!/bin/sh # file : /scripts/cdjava # cd /home/askgelal/projects/java
puis créez un alias dans votre fichier de démarrage.
#!/bin/sh # file /scripts/mastercode.sh # alias cdjava='. /scripts/cdjava'
- j'ai créé un fichier de démarrage où je vide tous mes Alias et fonctions personnalisées.
- alors je source ce fichier dans mon .bashrc doit le mettre sur chaque botte.
Par exemple, créer un fichier maître d'alias / fonctions: /scripts/mastercode.sh
(mettez le pseudonyme dans ce fichier.)
Puis à la fin de votre .bashrc fichier:
source /scripts/mastercode.sh
maintenant son cd facile à votre répertoire java, il suffit de taper cdjava et vous êtes y.
L'idée de Jeremy Ruten d'utiliser un lien symbolique a déclenché une pensée qui n'a traversé aucune autre réponse. Use:
CDPATH=:$HOME/projects
le point de départ est important; cela signifie que s'il y a un répertoire 'dir' dans le répertoire courant, alors ' cd dir
' va changer pour cela, plutôt que de sauter ailleurs. Avec la valeur définie comme indiqué, vous pouvez faire:
cd java
et, si il n'y a pas de sous-répertoire appelé java dans le répertoire courant, il vous conduira directement à $HOME/projets/java - pas d'alias, pas de scripts douteux execs ou dot de commandes.
Mon $HOME est /Users/jleffler; my $CHEMIN_CD est:
:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work
vous pouvez utiliser .
pour exécuter un script dans l'environnement shell actuel:
. script_name
ou alternativement, son alias plus lisible mais spécifique au shell source
:
source script_name
cela évite la sous-couche, et permet à n'importe quelle variable ou builtins (y compris cd
) d'affecter la couche courante à la place.
j'ai eu mon code à travailler en utilisant . <your file name>
./<your file name>
dose ne fonctionne pas parce qu'il ne change pas votre répertoire dans le terminal il change juste le répertoire spécifique à ce script.
Voici mon programme
#!/bin/bash
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace
Voici mon terminal
nova:~ Kael$
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$
utiliser exec bash
à la fin
un script bash opère sur son environnement actuel ou sur celui de son enfants, mais jamais sur son environnement parent.
Toutefois, cette question est souvent posée, car on veut être laissé à l'invite bash dans un certain répertoire, après l'exécution d'un script bash à partir d'un autre répertoire.
si tel est le cas, il suffit d'exécuter une instance de bash enfant à la fin du script:
#!/bin/bash
cd /home/tree/projects/java
exec bash
quand vous lancez un script shell, il exécute une instance nouvelle de ce shell ( /bin/bash
). Ainsi, votre script lance juste un shell, change le répertoire et sort. En d'autres termes, cd
(et d'autres commandes similaires) dans un script shell n'affectent pas le shell à partir duquel ils ont été lancés et n'y ont pas accès.
sur mon cas particulier j'ai eu besoin de trop de fois pour changer pour le même répertoire. Donc sur mon .bashrc (j'utilise ubuntu) j'ai ajouté le
1 -
$ nano ~./ bashrc
function switchp
{
cd /home/tree/projects/
}
2 -
$ source ~/.bashrc
3 -
$ switchp java
directement il fera: cd /accueil/arbre/projets/java
Espère que ça aide!
il ne modifie le répertoire que pour le script lui-même, alors que votre répertoire courant reste le même.
vous pouvez utiliser un lien symbolique à la place. Il vous permet de prendre un "raccourci" pour un fichier ou un répertoire, donc, vous n'avez qu'à taper quelque chose comme cd my-project
.
vous pouvez faire ce qui suit:
#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash
EDIT: Ce pourrait être "en pointillé" ainsi, pour empêcher la création de la suite des coquilles.
exemple:
. ./previous_script (with or without the first line)
vous pouvez combiner un alias et un script,
alias proj="cd \`/usr/bin/proj !*\`"
à condition que le script fasse écho au chemin de destination. Notez que ce sont des backticks entourant le nom du script.
par exemple, votre script pourrait être
#!/bin/bash
echo /home/askgelal/projects/java/
l'avantage de cette technique est que le script peut prendre n'importe quel nombre de paramètres de ligne de commande et émettre différentes destinations calculées par une logique éventuellement complexe.
pour naviguer rapidement dans les répertoires, il y a $CDPATH, cdargs, et des façons de générer des alias automatiquement
http://jackndempsey.blogspot.com/2008/07/cdargs.html
http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5827311.html
vous pouvez combiner l'alias D'Adam & Greg et les approches de points pour faire quelque chose qui peut être plus dynamique -
alias project=". project"
exécutant maintenant l'alias du projet exécutera le script du projet dans le shell actuel par opposition au sous-shell.
Vous pouvez utiliser l'opérateur && :
cd monrépertoire && ls
dans votre ~/.bash_profile fichier. ajouter la fonction suivante
move_me() {
cd ~/path/to/dest
}
redémarrer le terminal et vous pouvez taper
move_me
et vous serez déplacé dans le dossier de destination.
alors que le sourcing du script que vous voulez lancer est une solution, vous devez être conscient que ce script peut alors modifier directement l'environnement de votre shell actuel. De plus, il n'est plus possible de passer des arguments.
une autre façon de faire, est d'implémenter votre script comme une fonction dans bash.
function cdbm() {
cd whereever_you_want_to_go
echo "Arguments to the functions were , , ..."
}
cette technique est utilisée par autojump: http://github.com/joelthelion/autojump/wiki pour vous fournir l'apprentissage marque-pages de l'annuaire shell.
ça devrait faire ce que vous voulez. Changez le répertoire d'intérêt (à partir du script), puis lancez un nouveau shell bash.
#!/bin/bash
# saved as mov_dir.sh
cd ~/mt/v3/rt_linux-rt-tools/
bash
Si vous exécutez ce code, il vous mènera vers le répertoire d'intérêts et lorsque vous quittez il vous ramène à l'endroit original.
root@intel-corei7-64:~# ./mov_dir.sh
root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root@intel-corei7-64:~#
cela vous ramènera même à votre répertoire d'origine lorsque vous quitterez ( CTRL + d )
LOOOOOng de temps après, mais j'ai fait ce qui suit:
créer un fichier appelé case
coller le suivant dans le fichier:
#!/bin/sh
cd /home/""
enregistrer et ensuite:
chmod +x case
j'ai aussi créé un alias dans mon .bashrc
:
alias disk='cd /home/; . case'
maintenant quand je tape:
case 12345
essentiellement je tape:
cd /home/12345
vous pouvez tapez n'importe quel dossier après "affaire":
case 12
case 15
case 17
qui est comme dactylographier:
cd /home/12
cd /home/15
cd /home/17
respectivement
dans mon cas, le chemin est beaucoup plus long - ces gars l'ont résumé avec les ~ info plus tôt.
, Vous pouvez créer une fonction comme ci-dessous dans votre .bash_profile
et cela fonctionnera bien.
La fonction suivante prend un paramètre optionnel qui est un projet. Par exemple, vous pouvez juste exécuter
cdproj
ou
cdproj project_name
Voici la définition de la fonction.
cdproj(){
dir=/Users/yourname/projects
if [ "" ]; then
cd "${dir}/"
else
cd "${dir}"
fi
}
N'oubliez pas à la source de votre .bash_profile
Si vous utilisez poisson votre shell, la meilleure solution est de créer une fonction. Par exemple, étant donné la question originale, vous pouvez copier les 4 lignes ci-dessous et les coller dans votre ligne de commande de poisson:
function proj
cd /home/tree/projects/java
end
funcsave proj
cela créera la fonction et la sauvegardera pour l'utiliser plus tard. Si votre projet Change, répétez simplement le processus en utilisant le nouveau chemin.
Si vous préférez, vous pouvez ajouter manuellement le fichier de fonction en faisant ce qui suit:
nano ~/.config/fish/functions/proj.fish
et entrez le texte:
function proj
cd /home/tree/projects/java
end
et enfin appuyez sur ctrl+x pour sortir et y suivi de return pour enregistrer vos modifications.
( NOTE: la première méthode d'utilisation de funcsave crée le proj.les poissons fichier pour vous ).
j'ai un script bash simple appelé p pour gérer le changement de répertoire sur
github.com/godzilla/bash-stuff
il suffit de mettre le script dans votre répertoire bin local (/usr/local / bin)
et mettre
alias p='. p'
dans votre .bashrc
vous n'avez pas besoin de script, définissez seulement l'option correcte et créez une variable d'environnement.
shopt -s cdable_vars
dans votre ~/.bashrc
permet de cd
au contenu des variables d'environnement.
créer une telle variable d'environnement:
export myjava="/home/tree/projects/java"
et vous pouvez utiliser:
cd myjava
Utilisant Les Fonctions De Profil Bash:
L'une des fonctionnalités du profil bash est de stocker des fonctions personnalisées qui peuvent être exécutées dans le terminal ou dans des scripts bash de la même manière que vous exécutez des applications/commandes.ceci peut également être utilisé comme raccourci pour les commandes longues.
pour rendre votre fonction système efficace largement, vous aurez besoin de copier votre fonction à la fin de plusieurs fichiers
/home/user/.bashrc
/home/user/.bash_profile
/root/.bashrc
/root/.bash_profile
vous peut sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile
pour éditer / créer ces fichiers rapidement
Exemple De Script
faisant un raccourci vers cd ..
avec cdd
cdd() {
cd ..
}
ls raccourci
ll() {
ls -l -h
}
ls raccourci
lll() {
ls -l -h -a
}
Howto:
Copiez votre fonction à la fin de vos fichiers et redémarrez votre terminal vous pouvez puis lancez cdd
ou quelle que soit la fonction que vous avez écrite
noter la discussion comment définir le répertoire de travail du processus parent?
il contient quelques réponses hackish, par exemple
https://stackoverflow.com/a/2375174/755804 (changer le répertoire de processus parent via gdb, ne faites pas cela) et https://stackoverflow.com/a/51985735/755804 (la commande tailcd
qui injecte CD dirname au flux d'entrée du processus parent; eh bien, idéalement, il devrait être une partie de bash plutôt qu'un hack)
vous pouvez exécuter quelques lignes dans le même sous-puits si vous terminez les lignes avec backslash.
cd somedir; \
pwd