Як змусити `cd dir / filename` взяти мене до dir /?


10

Я б дуже зручно мати можливість використовувати cdз файлом аргументом.

cd myDirectory/anyname.anyExtension було б рівнозначно cd myDirectory/

Що було б найкращим псевдонімом або функцією для досягнення такої поведінки?

EDIT : Вибачте, що я не згадував це на 1-му місці: я використовуюzsh

Відповіді:


5

В zsh, я часто роблю:

cd /path/to/somefile(:h)

( hдля head).

Якщо somefileце симпосилання, ви також можете зробити:

cd somefile(:A:h)

Щоб потрапити в каталог, де може бути знайдено ціль символьного посилання.


zshЕквівалент Chris 'тепер bash-тільки рішення буде:

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

В zsh, ви можете також перевизначити які «слова» Ctrl-WВидаляє.

Таким чином zsh, "слова" в контексті віджетів на основі руху / транспонування / видалення - це послідовності alnum плюс символи $WORDCHARSзмінної, яка за замовчуванням включає /.

Ви можете видалити /з, $WORDCHARSщоб видалити Ctrl-Wлише один компонент шляху:

WORDCHARS=${WORDCHARS/\/}

Ще одне корисне розширення - select-word-styleвіджет, який ви можете використовувати для інтерактивного вибору між різними стилями слів.

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

Потім натискання Alt-Wдозволяє вибирати між різними стилями слів.

$ 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
?

Цікаво. (Я також використовую zsh).
Себастьян

Дуже цікава редакція про силу zshта стилі слів. Дякую також за zshкоманду. Це справляється бездоганно.
Себастьян

16

Я припускаю, що ви все ще хочете зберегти початковий функціонал, якщо ви вводите каталог, і ви використовуєте bash.

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

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

Якщо ви ніколи не будете використовувати опції CD ( -Pтощо), цього також буде достатньо:

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

4
якщо ви зміните ім'я функції cd, обов'язково додайте builtinперед cdдзвінками
Ульріх Дангел,

@Chris: Ви припустили, що правильно;) Дякую за цю функцію, готову до використання
Sébastien

Версія, що зберігає cdпараметри, не працює zsh. Простіше, з чим добре працює zsh, але cdНЕ вже еквівалентно cd ~: /
Себастьян

@Sebastien Спробуйте зараз, я думаю, що це має виправити.
Кріс Даун

@Chris, дійсно додавання чека [ -z "$1" ]було достатньо. Я прийняв відповідь Стефана, щоб надати їй більшої наочності, оскільки це, здається, є найкращим рішенням zsh.
Себастьян

7

Ви можете dirnameзняти ім'я файлу з шляху, наприклад,

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

Див man dirname.


3
Зауважте, що якщо ви введете каталог, це зміниться в каталог над цим каталогом, що може не бути бажаним (з питання, бажано це чи ні), незрозуміло).
Кріс Даун

1
@ChrisDown Правда, але я залишив це як вправу для читача, і ваша відповідь показує, як з цим боротися.
Адріан Фрюхвірт

1
@ AdrianFrühwirth Вправа! Га!

3

Якщо ви додасте це до свого .profile, завантажте його ( source ~/.profileабо вийдіть із системи та увійдіть знову), тоді mycd [file or directory]ви перейдете до потрібного каталогу:

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

Якщо ви його cdназвете, то відбудуться дивні речі.


1
Це порушиться, якщо ім'я каталогу містить пробіл, і вам потрібно закрити крапку з комою, щоб припинити командну групу. Редагував це для вас, сподіваюся, ви не заперечуєте.
Кріс Даун

@ChrisDown, хоча це стосується інших оболонок, крапка з комою не потрібно zsh.
Стефан Шазелас

Крім того, це порушується, якщо передача аргументів до cd, як -P.
Кріс Даун

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
}

З огляду на каталог, який називається $(sudo reboot), ця функція може перезавантажити систему. Також користувач використовує zsh, не bash.
Кусалаланда

Дайте будь-яку команду $ (sudo reboot), ця функція перезавантажить систему. Також +1 я спочатку не помітив "zsh" - хороший улов.
ecwpz91

Ні, cd '$(sudo reboot)'буде змінено каталог, тоді як ваша функція намагатиметься оцінити ім'я.
Кусалаланда

Ах, я бачу і внесла зміни. Дайте мені знати, чи це працює? Хороший улов.
ecwpz91
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.