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?

621
demandé sur codeforester 2008-11-01 05:07:08

29 réponses

Les scripts Shell

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"
528
répondu Greg Hewgill 2014-05-08 13:18:46

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.

418
répondu Adam Liss 2012-12-06 11:55:31

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.

198
répondu DigitalRoss 2012-11-13 04:52:17

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.)

128
répondu Tzachi.e 2016-11-18 14:26:03

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.

90
répondu Matt Thomas 2010-05-06 03:41:15

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
36
répondu Jonathan Leffler 2008-11-01 04:21:41

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.

29
répondu Sid 2018-07-09 02:55:55

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$ 
25
répondu kaelhop 2012-10-28 19:42:52

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
16
répondu Serge Stroobandt 2016-04-21 11:34:52

simplement exécuter:

cd /home/xxx/yyy && command_you_want
14
répondu warhansen 2017-03-10 14:33:04

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.

11
répondu Daniel Spiewak 2008-11-01 02:09:12

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!

9
répondu workdreamer 2015-07-30 08:46:44

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 .

7
répondu Jeremy Ruten 2008-11-01 02:10:01

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)
7
répondu Thevs 2008-11-01 04:27:38

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.

7
répondu J. A. Faucett 2013-10-12 14:37:42
5
répondu Gene T 2015-08-20 04:41:57

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.

5
répondu mogga 2012-02-09 07:33:41

Vous pouvez utiliser l'opérateur && :

cd monrépertoire && ls

3
répondu Jack Bauer 2013-03-24 16:56:27

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.

3
répondu mihai.ciorobea 2013-08-19 04:53:08

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.

3
répondu thomasd 2015-03-20 01:19:19

ç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 )

3
répondu jithu83 2018-05-03 14:29:07

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.

2
répondu chris 2011-07-09 16:20:41

, 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

1
répondu Krish 2018-01-10 07:54:09

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 ).

0
répondu Lane Roathe 2012-12-12 16:46:17

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

0
répondu godzilla 2013-10-02 10:43:15

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

autres variantes .

0
répondu Gauthier 2017-04-13 12:22:42

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

0
répondu intika 2018-04-10 08:16:09

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)

0
répondu 18446744073709551615 2018-08-23 12:46:05

vous pouvez exécuter quelques lignes dans le même sous-puits si vous terminez les lignes avec backslash.

cd somedir; \
pwd
-1
répondu Max 2013-04-06 10:02:43