Bagaimana cara membuat `cd dir / filename` membawa saya ke dir /?

10

Saya akan merasa sangat nyaman untuk dapat menggunakan cddengan berkas argumen.

cd myDirectory/anyname.anyExtension akan setara dengan cd myDirectory/

Apa alias atau fungsi terbaik untuk mencapai perilaku ini?

EDIT : Maaf saya tidak menyebutkannya di tempat pertama: Saya menggunakanzsh

Sébastien
sumber

Jawaban:

5

Dalam zsh, saya sering melakukan:

cd /path/to/somefile(:h)

( huntuk head).

Jika somefilesymlink, Anda juga dapat melakukan:

cd somefile(:A:h)

Untuk sampai ke direktori tempat target symlink dapat ditemukan.


The zshsetara dengan Chris' sekarang bashsolusi -hanya akan:

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

Di zsh, Anda juga dapat mendefinisikan kembali "kata" yang Ctrl-Wdihapus.

Dalam zsh, "kata-kata" dalam konteks gerakan berbasis kata / transpose / hapus widget adalah urutan alnum ditambah karakter dalam $WORDCHARSvariabel yang secara default termasuk /.

Anda dapat menghapus /dari $WORDCHARSsehingga Ctrl-Whanya menghapus satu komponen jalan:

WORDCHARS=${WORDCHARS/\/}

Ekstensi lain yang bermanfaat adalah select-word-stylewidget yang dapat Anda gunakan untuk secara interaktif memilih antara berbagai gaya kata.

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

Kemudian menekan Alt-Wmemungkinkan Anda untuk memilih di antara gaya kata yang berbeda.

$ 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
sumber
Menarik. (Saya menggunakan zsh juga).
Sébastien
Sunting yang sangat menarik tentang kekuatan zshdan gaya kata. Terima kasih juga atas zshperintahnya. Itu melakukan pekerjaan dengan sempurna.
Sébastien
15

Saya berasumsi Anda masih ingin mempertahankan fungsi asli jika Anda memasukkan direktori, dan Anda gunakan bash.

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

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

Jika Anda tidak akan pernah menggunakan opsi cd ( -P, dll), maka ini juga sudah cukup:

cd() { 
    if [ -d "$1" ] || [ -z "$1" ]; then
        builtin cd "$@"
    else
        builtin cd "${1%/*}"
    fi
}
Chris Down
sumber
4
jika Anda mengubah nama fungsi menjadi cd pastikan untuk menambahkan builtindi depan cdpanggilan
Ulrich Dangel
@ Chris: Anda berasumsi benar;) Terima kasih atas fungsi siap pakai ini
Sébastien
Versi yang mempertahankan cdopsi tidak berfungsi zsh. Yang lebih sederhana berfungsi dengan baik zsh, TETAPI cdtidak lagi setara dengan cd ~: /
Sébastien
@Sebastien Coba sekarang, saya pikir itu harus memperbaikinya.
Chris Down
@ Chris, memang menambahkan tanda centang [ -z "$1" ]sudah cukup. Saya telah menerima jawaban Stephane untuk memberikan lebih banyak visibilitas, karena tampaknya itu adalah solusi terbaik untuk itu zsh.
Sébastien
7

Anda dapat menggunakan dirnameuntuk menghapus nama file dari path, misalnya

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

Lihat man dirname.

Adrian Frühwirth
sumber
3
Perhatikan bahwa jika Anda memasukkan direktori, ini akan berubah ke direktori di atas direktori itu, yang mungkin tidak diinginkan (tidak jelas dari pertanyaan apakah ini diinginkan atau tidak).
Chris Down
1
@ ChrisDown Benar, tapi saya meninggalkannya sebagai latihan untuk pembaca dan jawaban Anda menunjukkan bagaimana menghadapinya.
Adrian Frühwirth
1
@ AdrianFrühwirth Latihan! Hah!
3

Jika Anda menambahkan ini ke Anda .profile, lalu muat ( source ~/.profileatau logout dan masuk lagi), maka mycd [file or directory]akan membawa Anda ke direktori yang benar:

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

Jika Anda menyebutkannya cd, maka hal-hal aneh akan terjadi.

jwhitlock
sumber
1
Ini akan pecah jika nama direktori berisi spasi putih, dan Anda memerlukan tanda koma penutup untuk mengakhiri grup perintah. Diedit untuk Anda, harap Anda tidak keberatan.
Chris Down
@ ChrisDown, meskipun itu berlaku untuk kerang lain, Anda tidak perlu titik koma penutup zsh.
Stéphane Chazelas
Juga, ini pecah jika melewati argumen untuk cd, suka -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
sumber
Diberi nama direktori $(sudo reboot), fungsi ini dapat mem-boot ulang sistem. Juga, pengguna menggunakan zsh, bukan bash.
Kusalananda
Berikan perintah $ (sudo reboot), fungsi ini akan reboot sistem. Juga, +1 pada awalnya saya tidak melihat 'zsh' - tangkapan yang bagus.
ecwpz91
Tidak, cd '$(sudo reboot)'akan mengubah direktori, sementara fungsi Anda akan mencoba untuk mengevaluasi nama.
Kusalananda
Ah, saya melihat dan membuat perubahan. Beri tahu saya jika itu berhasil? Tangkapan yang bagus.
ecwpz91