Comment faire pour que `cd dir / nom de fichier` m'emmène dans dir /?


10

Je trouverais très pratique de pouvoir l'utiliser cdavec un argument de fichier .

cd myDirectory/anyname.anyExtension serait équivalent à cd myDirectory/

Quel serait le meilleur alias ou la meilleure fonction pour obtenir ce comportement?

EDIT : Désolé, je ne l'ai pas mentionné à la 1ère place: j'utilisezsh

Réponses:


5

Dans zsh, je fais souvent:

cd /path/to/somefile(:h)

( hpour head).

Si somefileest un lien symbolique, vous pouvez également faire:

cd somefile(:A:h)

Pour accéder au répertoire où se trouve la cible du lien symbolique.


L' zshéquivalent de la bashsolution désormais unique de Chris serait:

cd() {
  [[ ! -e $argv[-1] ]] || [[ -d $argv[-1] ]] || argv[-1]=${argv[-1]%/*}
  builtin cd "$@"
}

Dans zsh, vous pouvez également redéfinir ce que les "mots" Ctrl-Wsuppriment.

Dans zsh, les "mots" dans le contexte des widgets de mouvement / transposition / suppression basés sur des mots sont des séquences d'aluns plus les caractères de la $WORDCHARSvariable qui inclut par défaut /.

Vous pouvez supprimer /de $WORDCHARSsorte que Ctrl-Wne supprime qu'un seul composant de chemin:

WORDCHARS=${WORDCHARS/\/}

Une autre extension utile est le select-word-stylewidget que vous pouvez utiliser pour choisir interactivement entre différents styles de mots.

autoload select-word-style
zle -N select-word-style
bindkey '\ew' select-word-style

Une pression sur Alt-Wvous permet de choisir entre différents styles de mots.

$ cd /blah/blih<Alt-W>
Word styles (hit return for more detail):
(b)ash (n)ormal (s)hell (w)hitespace (d)efault (q)uit
(B), (N), (S), (W) as above with subword matching
?

Intéressant. (J'utilise aussi zsh).
— Sébastien

Édition très intéressante sur la puissance des zshstyles de mots. Merci aussi pour la zshcommande. Il fait parfaitement l'affaire.
— Sébastien

15

Je suppose que vous souhaitez toujours conserver la fonctionnalité d'origine si vous entrez un répertoire et que vous l'utilisez bash.

cd() {
    local file="${!#}"

    if (( "$#" )) && ! [[ -d "$file" ]]; then
        builtin cd "${@:1:($#-1)}" "${file%/*}"
    else
        builtin cd "$@"
    fi
}

Si vous n'utilisez jamais les options de cd ( -P, etc.), cela suffira également:

cd() { 
    if [ -d "$1" ] || [ -z "$1" ]; then
        builtin cd "$@"
    else
        builtin cd "${1%/*}"
    fi
}

4
si vous changez le nom de la fonction en cd assurez-vous de l'ajouter builtindevant les cdappels
— Ulrich Dangel

@Chris: Vous avez bien compris;) Merci pour cette fonction prête à l'emploi
— Sébastien

La version qui conserve les cdoptions ne fonctionne pas avec zsh. Le plus simple fonctionne bien zsh, MAIS cdn'est plus équivalent comme cd ~: /
— Sébastien

@Sebastien Essayez maintenant, je pense que cela devrait résoudre ce problème.
— Chris Down

@Chris, en effet l'ajout d'une vérification [ -z "$1" ]était suffisant. J'ai accepté la réponse de Stéphane pour lui donner plus de visibilité, car elle semble être la meilleure solution zsh.
— Sébastien

7

Vous pouvez utiliser dirnamepour supprimer le nom de fichier du chemin d'accès, par exemple

mycd() { cd "$(dirname "$1")"; }

Tu vois man dirname.


3
Notez que si vous entrez un répertoire, cela changera dans le répertoire au - dessus de ce répertoire, ce qui peut ne pas être souhaité (il n'est pas clair de la question de savoir si cela est souhaité ou non).
— Chris Down

1
@ChrisDown C'est vrai, mais j'ai laissé cela comme un exercice au lecteur et votre réponse montre comment y faire face.
— Adrian Frühwirth

1
@ AdrianFrühwirth Un exercice! Hah!

3

Si vous ajoutez ceci à votre .profile, puis chargez-le ( source ~/.profileou déconnectez-vous et reconnectez-vous), puis vous mycd [file or directory]amènera au bon répertoire:

mycd() { if [ -d "$1" ]; then cd "$1"; else cd "$( dirname "$1" )"; fi ; }

Si vous le nommez cd, des choses étranges se produiront.


1
Cela se cassera si le nom du répertoire contient des espaces, et vous avez besoin d'un point-virgule de fermeture pour terminer le groupe de commandes. Je l'ai édité pour vous, j'espère que cela ne vous dérange pas.
— Chris Down

@ChrisDown, bien que cela soit vrai pour les autres shells, vous n'avez pas besoin du point-virgule de fermeture zsh.
— Stéphane Chazelas

En outre, cela se casse si vous passez des arguments à cd, comme -P.
— Chris Down

0
cd2() {
 arg=() dir= cmd= IFS=" " msg='[-L|[-P [-e]]|-h] [dir|file]'

 while [ "$#" -gt 1 ] ; do
  case "$1" in
   -h) printf "%s: cd2 %s\n" "$0" "$msg"
    return 1 ;;
   *) arg+=("$1") ;;
  esac
  shift
 done

 [ -f "${1:-}" ] && dir="$(dirname ${1:-})" || dir="${1:A}"
 [ ! -z "$arg" ] && cmd="cd ${arg[@]} $dir" || cmd="cd $dir"

 if ! $cmd 2>/dev/null; then
  printf "%s: cd2 %s\n" "$0" "$msg"
  return 1
 fi
}

Étant donné un répertoire appelé $(sudo reboot), cette fonction peut redémarrer le système. En outre, l'utilisateur utilise zsh, non bash.
— Kusalananda

Donnez n'importe quelle commande $ (sudo reboot), cette fonction redémarrera le système. De plus, +1 je n'ai pas remarqué 'zsh' au début - bonne prise.
— ecwpz91

Non, cd '$(sudo reboot)'changerait de répertoire, tandis que votre fonction essaierait d'évaluer le nom.
— Kusalananda

Ah, je vois et j'ai fait des changements. Faites-moi savoir si cela fonctionne? Bonne prise.
— ecwpz91
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.