¿Cómo hacer que `cd dir / filename` me lleve a dir /?

10

Me resultaría muy conveniente poder usarlo cdcon un argumento de archivo .

cd myDirectory/anyname.anyExtension sería equivalente a cd myDirectory/

¿Cuál sería el mejor alias o función para lograr este comportamiento?

EDITAR : Lo siento, no lo mencioné en primer lugar: usozsh

Sébastien
fuente

Respuestas:

5

En zsh, a menudo hago:

cd /path/to/somefile(:h)

( hpara head).

Si somefilees un enlace simbólico, también puede hacer:

cd somefile(:A:h)

Para llegar al directorio donde se puede encontrar el destino del enlace simbólico.


El zshequivalente de la bashúnica solución de Chris ahora sería:

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

En zsh, también puedes redefinir lo que las "palabras" Ctrl-Weliminan.

En zsh, "palabras" en el contexto de los widgets de movimiento / transposición / eliminación basados ​​en palabras son secuencias de alnums más los caracteres en la $WORDCHARSvariable que por defecto incluye /.

Puede eliminar /de $WORDCHARSmodo que Ctrl-Wsolo elimine un componente de ruta:

WORDCHARS=${WORDCHARS/\/}

Otra extensión útil es el select-word-stylewidget que puede usar para elegir interactivamente entre diferentes estilos de palabras.

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

Luego, presionar le Alt-Wpermite elegir entre diferentes estilos de palabras.

$ 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
?
Stéphane Chazelas
fuente
Interesante. (Yo uso zsh también).
Sébastien
Edición muy interesante sobre el poder zshy los estilos de palabras. Gracias también por el zshcomando. Hace el trabajo perfectamente.
Sébastien
15

Supongo que aún desea conservar la funcionalidad original si ingresa un directorio y lo está utilizando bash.

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

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

Si nunca va a utilizar las opciones de CD ( -P, etc.), esto también será suficiente:

cd() { 
    if [ -d "$1" ] || [ -z "$1" ]; then
        builtin cd "$@"
    else
        builtin cd "${1%/*}"
    fi
}
Chris Down
fuente
44
si cambia el nombre de la función a cd, asegúrese de agregar builtinen frente de las cdllamadas
Ulrich Dangel
@ Chris: Asumiste la razón;) Gracias por esta función lista para usar
Sébastien
La versión que conserva las cdopciones no funciona zsh. El más simple funciona bien zsh, PERO cdya no es equivalente a cd ~: /
Sébastien
@Sebastien Pruébalo ahora, creo que eso debería solucionarlo.
Chris Down
@ Chris, de hecho, agregar un cheque [ -z "$1" ]fue suficiente. Acepté la respuesta de Stephane para darle más visibilidad, ya que parece ser la mejor solución zsh.
Sébastien
7

Puede usar dirnamepara quitar el nombre de archivo de la ruta, p. Ej.

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

Ver man dirname.

Adrian Frühwirth
fuente
3
Tenga en cuenta que si ingresa un directorio, esto cambiará al directorio que se encuentra arriba de ese directorio, lo que puede no ser deseado (la pregunta no aclara si esto es deseado o no).
Chris Down
1
@ChrisDown Es cierto, pero lo dejé como un ejercicio para el lector y su respuesta muestra cómo lidiar con eso.
Adrian Frühwirth
1
@ AdrianFrühwirth Un ejercicio! Ja!
3

Si agrega esto a su .profile, luego lo carga ( source ~/.profileo cierra sesión y vuelve a iniciar sesión), mycd [file or directory]lo llevará al directorio correcto:

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

Si lo nombra cd, entonces sucederán cosas extrañas.

jwhitlock
fuente
1
Esto se interrumpirá si el nombre del directorio contiene espacios en blanco y necesita un punto y coma de cierre para terminar el grupo de comandos. Editado para ti, espero que no te importe.
Chris Down
@ChrisDown, aunque eso es cierto para otros shells, no necesita el punto y coma de cierre zsh.
Stéphane Chazelas
Además, esto se rompe si pasa argumentos a cd, como -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
}
ecwpz91
fuente
Dado un directorio llamado $(sudo reboot), esta función puede reiniciar el sistema. Además, el usuario está utilizando zsh, no bash.
Kusalananda
Dé cualquier comando $ (reinicio de sudo), esta función reiniciará el sistema. Además, +1 no noté 'zsh' inicialmente - buena captura.
ecwpz91
No, cd '$(sudo reboot)'cambiaría el directorio, mientras que su función intentaría evaluar el nombre.
Kusalananda
Ah, ya veo e hice cambios. Avísame si eso funciona? Buena atrapada.
ecwpz91