Script pour changer le répertoire courant (cd, pwd)

44

Je veux exécuter un script pour changer simplement le répertoire de travail actuel:

#!/bin/bash
cd web/www/project

Mais, après que je l'utilise, le pwd actuel reste inchangé! Comment puis je faire ça?

Sony Santos
la source

Réponses:

63

C'est un comportement attendu, et déjà discuté plusieurs fois.

Le script est exécuté dans un sous-shell et ne peut pas changer le répertoire de travail du shell parent. Ses effets sont perdus à la fin.

Pour changer de répertoire de façon permanente, vous devez source le script, comme dans

. ./script
enzotib
la source
8
@Sony: Notez que vous devriez utiliser returnpour échapper à un script créé de cette manière, non exit, elles ressemblent à des fonctions de shell et exitvont quitter le shell qui a généré le script.
Charles Stewart
@ CharlesStewart En fait, je ne suis pas familier avec les scripts sourced. Merci!
Sony Santos
5
est source ./scriptle même?
Amyassin
2
@amyassin: oui, c'est ça
enzotib
2
1. .et sourcesont égaux en bash. 2. nous n'avons pas besoin d'utiliser ./avant nom_fichier s'il se trouve dans le même répertoire. C'est ok pour ne courir que ça:. script
sobi3ch
19

Pour de petites tâches telles que celle-ci, au lieu de créer un script, créez un alias comme celui-ci,

$ alias cdproj='cd /dir/web/www/proj'

Vous devez l'ajouter à votre .bashrcfichier si vous souhaitez le définir pour chaque shell interactif.

Maintenant, vous pouvez exécuter ceci en tant que $ cdproj.

Sachin Divekar
la source
1
Vous pouvez également demander au script de faire écho aux commandes à exécuter, puis d'utiliser eval `./script` ou eval $(./script)d'exécuter ces commandes. Il s'agit d'une approche courante pour les commandes devant mettre à jour l'environnement du shell appelant.
Keith Thompson
2
Faites très attention à ce que vous affichez si vous allez suivre l' evalapproche.
jw013
13

Utiliser exec bashà la fin

Un script bash opère sur son environnement actuel ou sur celui de ses enfants, mais jamais sur son environnement parent.

Cependant, cette question est souvent posée car on veut être laissé à l’invite de bash dans un certain répertoire après l’exécution d’un script bash depuis un autre répertoire.

Si tel est le cas, exécutez simplement une instance de l'enfant bash à la fin du script:

#!/usr/bin/env bash
cd desired/directory
exec bash

Cela crée un nouveau sous-shell. Tapez exitpour revenir au premier shell où le script a été initialement lancé.

Serge Stroobandt
la source
Mieux vaut simplement se baser sur le script, comme dans la réponse acceptée: utiliser execest généralement considéré comme le dernier recours d'un scélérat .. :)
neuronet
1
cette astuce ne fonctionne pas dans debian 9 stretch.
Vdegenne
3
C'est la mauvaise façon de s'y prendre!
pause jusqu'à nouvel ordre.
4
Puisque personne n'a détaillé les problèmes avec ceci (je vous regarde, @Dennis): (1) Chaque fois que vous exécutez ceci, cela crée un nouveau processus de bash persistant. Faites-le dix ou vingt fois au cours d'une session et vous aurez de 11 à 21 processus Bash empilés. Cela peut affecter les performances et si vous essayez de mettre fin à la session proprement en tapant exit(ou en appuyant sur Ctrl + D), vous devrez le faire 11 à 21 fois. (2) L'utilisation d'un script exécutable présente un autre inconvénient: si vous définissez des options de shell (par exemple,  dotglobou  globstar) dans votre session de shell interactive, vous les perdrez, car vous démarrez un nouveau shell.
G-Man dit 'Réintégrez Monica' le
1
Très belle solution! J'ai réécrit mon alias dans bash_profile. Il s'agit maintenant d'un script stocké dans un fichier séparé. J'utilise le script pour accéder à un dossier temporaire nouvellement créé. Et maintenant, il est encore plus facile d’avoir une session bash temporaire. SRP en action! Merci!
artyom.razinov
8

Bien qu'il existe des réponses qui effectuent l'action exacte souhaitée, une méthode plus standard consiste à créer un lien symbolique:

ln -s ~/web/www/project proj   #use full path to dir!

Ensuite, vous pouvez accéder cdau répertoire en utilisant le nom proj:

cd proj

Cette méthode est plus flexible car vous pouvez accéder aux fichiers en utilisant le nom abrégé sans cd:

ls proj/   #note the endslash!
vim proj/file.x
corvinus
la source
4

Si vous passez d'un répertoire à l'autre dans le système de fichiers. Je recommanderai autojump .

stnly
la source
4

Selon ce que vous allez faire, une autre solution peut être de créer une fonction au lieu d’un script.

Exemple:

Créez une fonction dans un fichier, disons /home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

Ensuite, incluez-le dans votre fichier bashrcou zshrc:

# Somewhere in rc file
source /home/aidin/my-cd-script

Maintenant, vous pouvez l'utiliser comme une commande:

$ my-cd
Aide à
la source
0

Pourquoi ne pas utiliser "exec", il semble faire exactement ce que je souhaite.

#!/bin/bash

cd someplace
exec bash

~/someplace
Paul
la source
1
Méfiez-vous des choses qui semblent être ce que vous voulez. (Un cheval de bois géant! Tout ce que je voulais!) Chaque fois que vous exécutez cette opération, vous créez un nouveau processus de bash persistant. Faites-le dix ou vingt fois au cours d'une session et vous aurez de 11 à 21 processus bash empilés. Cela peut affecter les performances et si vous essayez de mettre fin à la session proprement en tapant exit(ou en appuyant sur Ctrl + D), vous devrez le faire 11 à 21 fois.
G-Man dit 'Réintégrez Monica' le
Je pouvais vraiment voir où cela poserait un problème. Pour moi, je l’utilise une fois, en effectuant le travail dont j’ai besoin, puis en le quittant. C’est le seul inconvénient avec lequel je peux vivre. D'autre part, s'il existe une meilleure solution, je suis prêt à l'examiner.
Paul
La réponse d'Aidin à cette question , en utilisant une fonction shell, et la réponse de Sachin Divekar , en utilisant un alias, sont (IMO) de meilleures solutions que l'utilisation d'un script. Post-scriptum Un autre inconvénient de l'utilisation d'un script est que, si vous définissez des options de shell (par exemple,  dotglobou  globstar), vous les perdrez, car vous démarrez un nouveau shell. … (Suite)
G-Man dit 'Réintégrez Monica' le
(Suite) ... PPS Je viens de remarquer que vous êtes, essentiellement, réitérant réponse de Serge Stroobandt et dire « » pourquoi pas ça? »Lors  pile échange nous espérons réponses à fournir de nouvelles idées et / ou de l' information, et non pas seulement examiner d'autres réponses.
G-Man dit 'Réinsérez Monica' le
-1

Vous pouvez le faire en utilisant une fonction ou en utilisant &&. Les exemples ci-dessous installent Zabbix et créent un fichier contenant une ligne.

Ex:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

ou:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
Raul Chiarella
la source