Je ne peux pas dire combien de fois j'ai souhaité une commande qui créerait un répertoire et se déplacerait dans ce répertoire. En gros, je voudrais l'équivalent de ce qui suit:
mkdir -p /arbitrarily/long/path; cd /arbitrarily/long/path
mais seulement avoir à taper /arbitrarily/long/path
une fois, quelque chose comme:
mk-cd /arbitrarily/long/path
J'ai essayé de créer un script pour cela, mais cela ne change que le répertoire dans le script. J'aimerais que le répertoire dans le shell change également.
#!/bin/bash
mkdir $1
cd $1
export PWD=$PWD
Comment pourrais-je être capable de faire ce travail?
cd
, vous avez choisi un cas spécial dès le début. : Dcd
informations super cool (revenir au répertoire précédent à l'aidecd -
, utiliserpushd
etpopd
maintenir une "pile" de répertoires): superuser.com/questions/324512/…mkdir -p /very/long/path
, puis utilisercd
espace, puis appuyer sur Alt +.
pour répéter le dernier argument, c'est-à-dire le nom du dir.mkdir -p /very/long/path; cd !#:2
. La chaîne!#:2
s'étendra à l'argument nr. 2 (c'est-à-dire le troisième argument/very/long/path
, puisque le décompte commence par zéro).!$
. J'utilise cette astuce tout le temps, même si vous pouvez faire beaucoup plus avec l'expansion de l'historique .Réponses:
Le moyen le plus simple consiste à utiliser une fonction shell:
Placez-le dans votre
.bashrc
fichier pour qu'il soit disponible comme une autre commande shell.La raison pour laquelle cela ne fonctionne pas en tant que script externe est
cd
que le répertoire en cours du script en cours d'exécution change, mais n'affecte pas celui qui appelle. C'est par conception! Chaque processus a son propre répertoire de travail qui est hérité par ses enfants, mais l'inverse n'est pas possible.Sauf si une partie du pipeline est exécutée en arrière-plan ou explicitement dans un sous-shell, une fonction shell ne s'exécute pas dans un processus séparé, mais dans le même processus, comme si la commande avait été obtenue. Le shell du répertoire actuel peut ensuite être modifié par une fonction.
Le terme
&&
utilisé ici pour séparer les deux commandes utilisées signifie que, si la première commande réussit (mkdir
), exécutez la seconde (cd
). Par conséquent, simkdir
le répertoire demandé ne parvient pas à être créé, il ne sert à rien d'essayer de s'y rendre. Un message d'erreur est imprimé parmkdir
et c'est tout.L'
-p
option utilisée avecmkdir
est là pour indiquer à cet utilitaire de créer tout répertoire manquant faisant partie du chemin d'accès complet du nom de répertoire passé en argument. Un effet secondaire est que si vous demandez à créer un répertoire déjà existant, lamkcd
fonction n'échouera pas et vous vous retrouverez dans ce répertoire. Cela pourrait être considéré comme un problème ou une fonctionnalité. Dans le premier cas, la fonction peut être modifiée par exemple de cette manière, qui prévient simplement l'utilisateur:Sans cette
-p
option, le comportement de la fonction initiale aurait été très différent.Si le répertoire contenant le répertoire à créer n'existe pas déjà, la fonction
mkdir
échoue.Si le répertoire à créer existe déjà,
mkdir
échoue également etcd
n'est pas appelé.Enfin, notez que définir / exporter
PWD
est inutile, car le shell le fait déjà en interne.Edit: j'ai ajouté l'
--
option aux deux commandes pour que la fonction autorise un nom de répertoire commençant par un tiret.la source
~/.bashrc
un des autres scripts d'initialisation.alias mk-cd 'mkdir -p \!:1; cd \!:1'
sans fonction? Ou peut-être devrais-je commencer à penser aux fonctions bash plutôt à des alias étendus?csh
mécanisme de transmission d'argument n'est pas implémenté avec des alias de style bourne. Les fonctions sont en effet la voie à suivre, étant beaucoup plus flexible.bar
). Une autre option consisterait à utiliserhistory 1
, comme dansalias mk-cd='args="$(history 1)" && args="${args#*mk-cd\ }" && mkdir -p "$args" && cd'
- cela fonctionne bien pour l'exemple de l'interrogateur, mais ce n'est pas une solution générale, car toute autre commande sur la même ligne (par exemple, la canalisation de la sortie) entraînera son échec.Je voudrais ajouter une solution alternative.
Votre script va fonctionner si vous invoquez avec la
.
ousource
commande:Si vous faites cela,
export
le script n'est pas nécessaire. Vous pouvez éviter de taper le.
en utilisant unalias
:Cela s'explique par le fait qu'un script s'exécute normalement dans un sous-shell, de sorte que son environnement est perdu à la fin, mais que la commande
.
(ousource
) l'oblige à s'exécuter dans le shell en cours.Cette technique peut être utile pour les séquences de commandes trop complexes pour une fonction ou en cours de développement et fréquemment éditées: une fois la commande
alias
entrée.bash_aliases
, vous pouvez éditer le script à volonté sans réinitialiser.Notez ce qui suit: -
Si vous écrivez un script qui doit être appelé avec la commande
.
/source
, vous pouvez vous en assurer de deux manières: -Pour une raison quelconque, un script appelé avec
.
/source
ne doit pas nécessairement être exécutable, supprimez donc simplement cette autorisation et le script ne sera pas trouvé dans "$ PATH" ou donnera une erreur d'autorisation s'il est appelé avec un chemin explicite.Alternativement, l'astuce suivante peut être utilisée à la tête du script:
Cela fonctionne parce que dans un sous-shell
bind
, un avertissement est émis, mais aucun statut d'erreur: ilread
est donc utilisé pour donner une erreur sur aucune entrée.la source
.
. J'ai fait d'. .bashrc
innombrables fois, mais je ne savais pas quoi faire exactement.
. Est-ce similaire àexport
?export var
copie la variable internevar
dans l'environnement, où elle est héritée et importée en tant que variable dans un sous-shell, mais cela n'a aucun effet sur un shell parent. Normalement, un sous-shell est créé pour exécuter un script et toutes les modifications apportées (y compris les variables exportées) sont perdues à la fin. Pour qu'un script puisse définir des variables dans un shell, il doit être exécuté dans ce shell. La.
commande agit ainsi: exécutez le script sans créer de sous-shell. Curieusement, les scripts exécutés par.
n’ont pas besoin d’autorisation exécutable..
etexport
, le titre de cette question ne vous mènerait pas à attendre une réponse ici. Je vais donc laisser ma réponse telle qu'elle est, mais merci pour votre commentaire.Pas une seule commande, mais vous n'avez pas à retaper tout le chemin, il suffit d'utiliser
!$
(qui est le dernier argument de la commande précédente dans l'historique du shell).Exemple:
la source
En créant des alias . Un moyen très populaire pour créer vos propres commandes.
Vous pouvez créer un alias à la volée:
C'est ça. Si vous souhaitez conserver cet alias de manière permanente (pas uniquement la session en cours), placez cette commande dans un fichier point (généralement ~ / .bash_aliases ou ~ / .bash_profile).
la source
En plus de ce qui a déjà été suggéré, je voudrais recommander Thefuck . C'est un framework Python pour rationaliser votre processus shell en corrigeant les erreurs. Inspiré par ce tweet , tout ce que vous avez à faire est de taper votre alias configuré (par défaut
fuck
) et il tentera de corriger votre commande précédente. Une de ses corrections se comporte comme suit:la source