Bash CD до тех пор, пока в определенной папке


16

Я много работаю в Magento, как и многие люди, с которыми я работаю, и раздражает необходимость набирать:

компакт диск ../../../../../../

Чтобы найти только несколько каталогов из корневой папки «httpdocs», я пытаюсь создать скрипт, следующий за этим псевдокодом:

while lowest level directory != httpdocs
    cd ../
end while;

Кажется довольно простым, я предполагаю, что мне нужно было бы выполнить некоторую форму grep при проверке, является ли последняя часть текущего рабочего каталога httpdocs, если не просто продолжать подниматься до уровня, пока он не станет правдой.

Я смотрел на изучение bash для этого, хотя кажется, что уже должно быть что-то похожее, и синтаксис озадачивает меня до бесконечности.

Ответы:


8

Это должна быть функция оболочки , а не сценарий, потому что сценарий выполняется в новой оболочке (и, следовательно, не может изменить каталог исходной оболочки).

function cdroot()
{
  while [[ $PWD != '/' && ${PWD##*/} != 'httpdocs' ]]; do cd ..; done
}

Конечно, вы можете назвать функцию как угодно.

Некоторое объяснение: Первый метод test ( $PWD != '/') является отказоустойчивым на тот случай, cdrootесли вы не находитесь в папке httpdocs. Это прекратится, когда вы доберетесь до корня.

Второй тест ( ${PWD##*/} != 'httpdocs') немного сложнее. $PWDпеременная, содержащая путь к текущему каталогу ${PWD##*/}обрезает все, вплоть до последней косой черты.


Недостатком этого итеративного является то, что вы теряете способность просто делать cd -потом, чтобы вернуться туда, где вы были.
Иезекииль Мунс

27

У меня есть функция, uptoвызванная в моем .bashrc, которая позволяет вам перейти в любой каталог по текущему пути по имени:

upto ()
{
    if [ -z "$1" ]; then
        return
    fi
    local upto=$1
    cd "${PWD/\/$upto\/*//$upto}"
}

У меня также есть завершение для этой функции, так что оно дает мне действительные имена каталогов и завершение, когда я нажимаю Tab:

_upto()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local d=${PWD//\//\ }
    COMPREPLY=( $( compgen -W "$d" -- "$cur" ) )
}
complete -F _upto upto

Кроме того, у меня есть еще одна функция, jdкоторая позволяет мне переходить в любой каталог ниже текущего:

jd(){
    if [ -z "$1" ]; then
        echo "Usage: jd [directory]";
        return 1
    else
        cd **"/$1"
    fi
}

Пример:

[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto h[TAB][TAB]
habitat       hippopotamus
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $ jd images
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ 

Вы также можете добавить псевдоним для upto httpdocs.
Cjm

@drogbane: jdкажется, не работает в каждом случае, вы не могли бы объяснить, как это работает?
Цезарь

@ Сезар использует globstar ( **). Чтобы включить эту функцию в вашей оболочке bash, используйте shopt -s globstar.
Dogbane

2
Это так блестяще сделано, я бы хотел дважды проголосовать.
droope

1
Я включил динамическое обнаружение и активацию магазина в jdфункцию, см. Gist.github.com/Rob--W/5888648 . Я тестировал только с Bash 4.2.45, так что YMMV.
Роб W

5

Простейшая функция bash, которую вы можете вставить в свою, .bashrcкоторую я могу себе представить (простая, потому что она не использует циклы или внешние процессы):

cdup() {
    cd "${PWD/\/httpdocs\/*//httpdocs}"
}

Это использует расширение параметра подстановки Pattern, чтобы заменить все после /httpdocs/in $PWDна `/ httpdocs '. Это выглядит очень грязно, потому что мы должны избегать прямой косой черты в пути, чтобы отличить их от прямой косой черты в синтаксисе расширения bash. Плюс не избегайте косых черт в строке замены, так что это также выглядит противоречивым.

Если нет /httpdocs/в текущем пути, тогда никакие замены не будут выполнены, и это просто переключится на текущий каталог.

Например, подстановка будет заменена /a/b/c/httpdocs/e/f/gна /a/b/c/httpdocsи cdв этот каталог.

Функция должна быть в вашей текущей среде оболочки (как функция или псевдоним), так как дочерний процесс не может изменить текущий каталог своего родителя. Вот почему я говорю, чтобы поместить его в ваш, .bashrcа не в сценарии оболочки.


Кстати, стоит упомянуть, что это позволит вам занять как можно более высокое место в иерархии (что, пожалуй, в любом случае является наиболее полезным вариантом использования).
Ибрагим

3

Вы также можете добавить что-то вроде этого в свой профиль:

alias cdh='cd $(echo $PWD | sed -e "s/\(.*\/httpdocs\)\/.*/\1/")'

Просто набрав, cdhвы попадете в самый верхний httpdocsкаталог в вашем текущем пути.


2

Это не полностью решит вашу проблему, но сэкономит cd ../../../../../../немного времени. Я заимствовал это из поста пользователя unknown здесь .


до N

подпрыгнуть N каталогов вверх в дереве каталогов

Вместо того, чтобы печатать

cd ../../../..

вы просто печатаете

up 4

и

cd -    

верну тебя

Поместите функцию в ваш .bashrc, чтобы использовать ее.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.