Wie bringe ich `cd dir / filename` dazu, mich zu dir / zu bringen?

10

Ich würde es sehr bequem , die Lage sein , zu verwenden cdmit einem Datei - Argumente.

cd myDirectory/anyname.anyExtension wäre gleichbedeutend mit cd myDirectory/

Was wäre der beste Alias ​​oder die beste Funktion, um dieses Verhalten zu erreichen?

EDIT : Sorry, ich habe es nicht an erster Stelle erwähnt: Ich benutzezsh

Sébastien
quelle

Antworten:

5

In zshmache ich oft:

cd /path/to/somefile(:h)

( hfür head).

Wenn somefilees sich um einen Symlink handelt, können Sie auch Folgendes tun:

cd somefile(:A:h)

Um zu dem Verzeichnis zu gelangen, in dem sich das Ziel des Symlinks befindet.


Das zshÄquivalent zu Chris 'jetzt basheinziger Lösung wäre:

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

In zshkönnen Sie auch neu definieren, welche "Wörter" Ctrl-Wentfernt werden.

In zsh"Wörter" im Kontext der wortbasierten Widgets zum Verschieben / Transponieren / Löschen sind Sequenzen von Alnums plus die Zeichen in der $WORDCHARSVariablen, die standardmäßig enthalten sind /.

Sie könnten entfernen /aus , $WORDCHARSso dass Ctrl-Wnur löscht eine Pfadkomponente:

WORDCHARS=${WORDCHARS/\/}

Eine weitere nützliche Erweiterung ist das select-word-styleWidget, mit dem Sie interaktiv zwischen verschiedenen Wortstilen wählen können.

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

Durch Drücken von Alt-Wkönnen Sie zwischen verschiedenen Wortstilen wählen.

$ 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
quelle
Interessant. (Ich benutze auch zsh).
Sébastien
Sehr interessante Bearbeitung über die Kraft zshund Wortstile. Danke auch für den zshBefehl. Es macht den Job perfekt.
Sébastien
15

Ich gehe davon aus, dass Sie die ursprüngliche Funktionalität beibehalten möchten, wenn Sie ein Verzeichnis eingeben und verwenden bash.

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

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

Wenn Sie niemals die Optionen von cd ( -Pusw.) verwenden, reicht dies auch aus:

cd() { 
    if [ -d "$1" ] || [ -z "$1" ]; then
        builtin cd "$@"
    else
        builtin cd "${1%/*}"
    fi
}
Chris Down
quelle
4
Wenn Sie den Funktionsnamen in cd ändern, stellen Sie sicher, dass Sie builtinvor den cdAufrufen hinzufügen
Ulrich Dangel
@ Chris: Sie haben richtig angenommen;) Danke für diese gebrauchsfertige Funktion
Sébastien
Die Version, die cdOptionen beibehält, funktioniert nicht mit zsh. Das einfachere funktioniert gut zsh, ABER cdist nicht mehr gleichbedeutend mit cd ~: /
Sébastien
@Sebastien Versuchen Sie es jetzt, ich denke, das sollte das beheben.
Chris Down
@ Chris, in der Tat war das Hinzufügen eines Checks [ -z "$1" ]ausreichend. Ich habe Stephanes Antwort akzeptiert, um sie sichtbarer zu machen, da sie die beste Lösung für zu sein scheint zsh.
Sébastien
7

Sie können dirnameden Dateinamen aus dem Pfad entfernen, z

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

Siehe man dirname.

Adrian Frühwirth
quelle
3
Beachten Sie, dass sich bei der Eingabe eines Verzeichnisses das Verzeichnis über diesem Verzeichnis ändert , was möglicherweise nicht erwünscht ist (aus der Frage, ob dies erwünscht ist oder nicht, geht nicht hervor).
Chris Down
1
@ChrisDown Stimmt, aber ich habe das als Übung dem Leser überlassen und Ihre Antwort zeigt, wie man damit umgeht.
Adrian Frühwirth
1
@ AdrianFrühwirth Eine Übung! Hah!
3

Wenn Sie dies zu Ihrem hinzufügen .profile, es dann laden ( source ~/.profileoder sich abmelden und erneut anmelden), gelangen mycd [file or directory]Sie in das richtige Verzeichnis:

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

Wenn Sie es nennen cd, werden seltsame Dinge passieren.

jwhitlock
quelle
1
Dies wird unterbrochen, wenn der Verzeichnisname Leerzeichen enthält und Sie ein schließendes Semikolon benötigen, um die Befehlsgruppe zu beenden. Habe es für dich bearbeitet, hoffe es macht dir nichts aus.
Chris Down
@ChrisDown, obwohl dies für andere Shells gilt, benötigen Sie das schließende Semikolon nicht zsh.
Stéphane Chazelas
Auch diese Pausen , wenn vorbei args cd, wie -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
quelle
Bei einem angegebenen Verzeichnis $(sudo reboot)kann diese Funktion das System neu starten. Auch der Benutzer verwendet zshnicht bash.
Kusalananda
Geben Sie einen Befehl $ (sudo reboot) ein. Diese Funktion startet das System neu. Außerdem, +1 habe ich 'zsh' anfangs nicht bemerkt - guter Fang.
ecwpz91
Nein, cd '$(sudo reboot)'würde das Verzeichnis wechseln, während Ihre Funktion versuchen würde, den Namen auszuwerten.
Kusalananda
Ah, ich sehe und habe Änderungen vorgenommen. Lassen Sie mich wissen, ob das funktioniert? Guter Fang.
ecwpz91