web-dev-qa-db-fra.com

Existe-t-il un one-liner qui me permet de créer un répertoire et d'y accéder en même temps?

Je me retrouve à répéter beaucoup de:

mkdir longtitleproject
cd longtitleproject

Existe-t-il un moyen de le faire sur une seule ligne sans répéter le nom du répertoire? Je suis bash ici.

166
methodofaction

Il n'y a pas de commande intégrée, mais vous pouvez facilement écrire une fonction qui appelle mkdir puis cd:

mkcd () {
  mkdir "$1"
  cd "$1"
}

Mettez ce code dans votre ~/.bashrc fichier (ou ~/.kshrc pour les utilisateurs de ksh, ou ~/.zshrc pour les utilisateurs de zsh). Il définit une fonction appelée mkcd. "$1" sera remplacé par l'argument de la fonction lorsque vous l'exécuterez.

Cette version simple présente plusieurs défauts:

  • Vous ne pouvez pas créer une chaîne de sous-répertoires à la fois. Correction: passez le -p option pour mkdir. (Cela peut être souhaitable ou non, car cela augmente le risque qu'une faute de frappe ne soit pas détectée, par exemple mkcd mydierctory/newsub créera avec plaisir mydierctory et mydierctory/newsub lorsque vous vouliez créer newsub à l'intérieur du mydirectory.) existant
  • Si l'argument commence par - mais pas seulement -, puis mkdir et cd l'interpréteront comme une option. Si c'est juste -, puis cd l'interprétera comme signifiant $OLDPWD. Si c'est + suivi de 0 ou plusieurs chiffres, puis cd dans zsh l'interprétera comme un index dans la pile de répertoires. Vous pouvez résoudre le premier problème, mais pas les deux autres, en passant -- avant l'argument. Vous pouvez résoudre tous ces problèmes en ajoutant ./ à l'argument s'il s'agit d'un chemin relatif.
  • mkdir ne suit pas CDPATH, mais cd le fait, donc si vous avez défini CDPATH sur une valeur qui ne commence pas par . (une configuration certes quelque peu inhabituelle), alors cd peut vous amener dans un répertoire différent de celui qui vient d'être créé. Prepending ./ aux chemins relatifs corrige cela (cela fait ignorer CDPATH).
  • Si mkdir échoue, il essaie d'exécuter cd. Correction: utilisez && pour séparer les deux commandes.

Encore assez simple:

mkcd () {
  case "$1" in /*) :;; *) set -- "./$1";; esac
  mkdir -p "$1" && cd "$1"
}

Cette version a encore le potentiel de faire entrer cd dans un répertoire différent de celui que mkdir vient de créer dans un cas Edge: si l'argument de mkcd contient .. et passe par un lien symbolique. Par exemple, si le répertoire actuel est /tmp/here et mylink est un lien symbolique vers /somewhere/else, puis mkdir mylink/../foo crée /somewhere/else/foo tandis que cd mylink/../foo se transforme en foo. Il ne suffit pas de rechercher des liens symboliques dans l'argument, car le Shell suit également les liens symboliques dans son propre répertoire actuel, donc cd /tmp/mylink; mkdir ../foo; cd ../foo ne se transforme pas dans le nouveau répertoire (/somewhere/else/foo) mais en /tmp/foo. Un correctif consiste à laisser le cd intégré résoudre tout .. les composants de chemin d'abord (cela n'a pas de sens d'utiliser foo/.. si foo n'existe pas, donc mkdir n'a jamais besoin de voir ..).

Nous arrivons à cette version robuste mais légèrement sanglante:

mkcd () {
  case "$1" in
    */..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
    /*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
    /*) mkdir -p "$1" && cd "$1";;
    */../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
    ../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
    *) mkdir -p "./$1" && cd "./$1";;
  esac
}

(Exercice: pourquoi j'utilise un sous-shell pour le premier cd appel?)

Si mkdir échoue, je veux être sûr de ne pas changer le répertoire courant. Revenir en arrière avec cd - ou $ OLDPWD n'est pas suffisant si le shell n'a pas la permission de changer dans son répertoire actuel. En outre, l'appel de cd met à jour OLDPWD, nous ne voulons donc le faire qu'une seule fois (ou restaurer OLDPWD).


Il existe également des moyens moins spécialisés pour ne pas avoir à retaper le mot de la ligne précédente:

  • Tapez cd, puis Esc. (ou Alt+.) pour insérer le dernier argument de la commande précédente.
  • cd !$ exécute cd sur le dernier argument de la commande précédente.
  • Presse Up pour rappeler la ligne de commande précédente, puis modifiez-la pour changer mkdir en cd.

C'est la doublure dont vous avez besoin. Aucune autre configuration nécessaire:

mkdir longtitleproject && cd $_

Le $_ variable, en bash, est le dernier argument donné à la commande précédente. Dans ce cas, le nom du répertoire que vous venez de créer. Comme expliqué dans man bash:

_         At  Shell  startup,  set to the absolute pathname used to invoke
          the Shell or Shell script being executed as passed in the  envi‐
          ronment  or  argument  list.   Subsequently, expands to the last
          argument to the previous command, after expansion.  Also set  to
          the  full  pathname  used  to  invoke  each command executed and
          placed in the environment exported to that command.  When check‐
          ing  mail,  this  parameter holds the name of the mail file cur‐
          rently being checked."$_" is the last argument of the previous command.

Utilisation cd $_ pour récupérer le dernier argument de la commande précédente au lieu de cd !$ parce que cd !$ donne le dernier argument de la commande précédente dans l'historique Shell:

cd ~/
mkdir folder && cd !$

vous vous retrouvez à la maison (ou ~ /)

cd ~/
mkdir newfolder && cd $_

vous vous retrouvez dans un nouveau dossier sous la maison !! (ou ~/newfolder)

151
Jesús Carrera

Il ne me serait jamais venu à l'esprit d'écrire ce comportement parce que j'entre les informations suivantes toutes les heures ...

$ mkdir someDirectory<ENTER>
$ cd !$

où bash remplace gentiment !$ avec le dernier mot de la dernière ligne; c'est-à-dire le nom de répertoire long que vous avez entré.

De plus, l'achèvement du nom de fichier est votre ami dans de telles situations. Si votre nouveau répertoire était le seul fichier du dossier, un double rapide TAB vous donnerait le nouveau répertoire sans le ressaisir.

Bien que ce soit cool que bash vous permette de créer des scripts pour des tâches courantes comme les autres réponses le suggèrent, je pense qu'il est préférable d'apprendre les fonctionnalités d'édition de ligne de commande que bash a à offrir afin que lorsque vous travaillez sur une autre machine, vous ne manquez pas la syntaxe sucre que vos scripts personnalisés fournissent.

30
Rob

Selon Quelles personnalisations avez-vous faites sur votre profil Shell pour augmenter la productivité? , voici comment je le fais:

# make a directory and cd to it
mcd()
{
    test -d "$1" || mkdir "$1" && cd "$1"
}

cela signifie qu'il fonctionne également si le répertoire existe déjà.

17
Mikel

Si vous utilisez Oh My Zsh, il existe une commande appelée take qui fait exactement cela. Cela ressemblerait à quelque chose comme ça.

take myfolder

J'ai trouvé celui-ci par accident. Je viens de regarder et il est répertorié sur ce cheatsheat du wiki Oh My Zsh GitHub. C'est une commande assez utile et apparemment très facile à créer vous-même.

16
Jordan Harris

Ou vous pouvez simplement créer une variable courte à la volée et l'utiliser deux fois x = longproject ; mkdir $x ; cd $x - ce qui, je l'avoue, est encore plus long que l'utilisation d'une fonction shellscript :)

3
sakisk

J'ai fait un script qui crée le répertoire et ensuite les cd, puis je lui ai donné un alias. Et voici un Gist où je le décris.

https://Gist.github.com/rehnen/34236d6ff270ccaa74b6#mkdir-like-it-was-meant-to-be

0
Marcus Rehn

Voici une légère variante qui mérite d'être mentionnée:

function mkdir() {
    local dir=$1
    command mkdir "$dir"  &&  cd "$dir"
}

Ajoutez ceci à votre ~/.bash_profile et vous pouvez ensuite utiliser mkdir comme d'habitude (une fois que vous l'avez source '), sauf que maintenant il exécutera la fonction ci-dessus plutôt que la commande standard mkdir .

Remarque, cela ne valide pas l'entrée conformément à l'acceptation réponse de Gilles , mais montre comment vous pouvez (efficacement) remplacer les commandes intégrées.

D'après la documentation (paraphrasant légèrement):

command mkdir [args] exécute mkdir avec args en ignorant toute fonction Shell nommée mkdir. Seules les commandes intégrées de Shell ou les commandes trouvées en recherchant le PATH sont exécutées. S'il existe une fonction Shell nommée ls, l'exécution de command ls dans la fonction exécutera la commande externe ls au lieu d'appeler la fonction récursivement

Je crois que builtin obtient un résultat similaire à command.

0
Arj

Ajout d'une fonction d'assistance à BASH, ZSH ou KSH

Créez la commande mkcd dans votre environnement en une seule ligne

echo -e 'mkcd() {\n mkdir -p "$1" && cd $_\n}' >> ~/.${0//-/}rc && . ~/.${0//-/}rc
0
Proximo