Який швидкий спосіб командного рядка для перемикання між декількома каталогами для адміністрування системи?


46

Який швидкий спосіб командного рядка для перемикання між декількома каталогами для адміністрування системи? Я маю на увазі, що я можу використовувати pushd .і popdперемикати, але що робити, якщо я хочу зберігати кратні і переходити через них, а не постійно вискакувати їх у нижній частині стека?


$CDPATHможливо?
roaima

6
о мій - я щойно дізнався про це cd -після того, як гуглінг викликав це питання.
Нахт - Відновлення Моніки

@Nacht: Як ви орієнтувались у структурі файлів раніше ??
самотній човен

1
Робили cdскрізь вручну. Було боляче. Хоча використовується автоматичне завершення за допомогою клавіші вкладки.
Воломійка

1
Можливо, ви хочете спробувати . Надзвичайно зручно, коли ви багато стрибаєте навколо однієї пари.
Рольф

Відповіді:


28

Використовуйте , pushdа потім спеціальні імена каталогів в вашому стеку каталогів: ~1, ~2і т.д.

Приклад:

tmp $ dirs -v
 0  /tmp
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
tmp $ cd ~3
music $ dirs -v
 0  /tmp/music
 1  /tmp/scripts
 2  /tmp/photos
 3  /tmp/music
 4  /tmp/pictures
music $ cd ~2
photos $ cd ~4
pictures $ cd ~3
music $ cd ~1
scripts $ 

Найефективніший спосіб використання pushdтаким способом - це завантаження списку ваших каталогів, потім додайте ще один каталог, який буде вашим поточним каталогом, і тоді ви можете переходити між статичними номерами, не впливаючи на положення каталогів у вашому стеку.


Варто також зазначити, що cd -переведе вас до останнього каталогу, в якому ви були. Так і буде cd ~-.

Перевага ~-над справедливим -полягає в тому, що -є специфічним cd, тоді ~-як розширюється вашою оболонкою так само ~1, як ~2і т.д. Це стане в нагоді при копіюванні файлу між дуже довгими шляхами до каталогу; наприклад:

cd /very/long/path/to/some/directory/
cd /another/long/path/to/where/the/source/file/is/
cp myfile ~-

Вищезазначене еквівалентно:

cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/

1
Також можна скористатисяcd -
Воломіке

cd -діє як Forth DROP DUP, наприклад, якщо починається з каталогу a , зі стеком abcd , cd -змінює стек на bbcd . Можливо, це bashпомилка, оскільки секунда cd -змінює стек назад на abcd . З цього ми можемо зробити висновок, що cd -використовує окрему структуру даних для зберігання попереднього каталогу, крім зміни стека.
agc

3
@agc, cd -використовує $OLDPWDі більше нічого.
Wildcard

Можливо, це cd -було раніше функцією bash , потім пізніше вони додали стек, але боялися зламати старий код більше, ніж хотіли простішого дизайну. Виправлення до попереднього, cd -діє чимось на зразок Forth OLDPWD @ SWAP OLDPWD ! DUP . На відміну cd foo, cd -друкує ім'я заміненого каталогу.
agc

Або завжди є інтерактивна кнопкова обгортка (інші відповіді на це питання включають автоперемикання тощо тощо).
Марно

42

bashВбудований pushdза допомогою +та -параметрів може обертати стек каталогів. Синтаксис може бути трохи заплутаним, можливо, тому, що цей стек є масивом, що базується на нулі . Ці прості функції обгортки проходять через стек каталогів:

# cd to next     directory in stack (left  rotate)
ncd(){ pushd +1 > /dev/null ; }
# cd to previous directory in stack (right rotate)
pcd(){ pushd -0 > /dev/null ; }

Тест: встановіть стек із чотирьох каталогів.

dirs -c   # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp

Тепер / tmp - поточний каталог, і стек виглядає так:

/tmp /bin /etc /home

Перейдіть до наступного каталогу в стеку (і покажіть його) чотири рази:

ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd

Вихід:

/bin
/etc
/home
/tmp

Змініть попередній каталог у стеці (і покажіть його) чотири рази:

pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd

Вихід:

/home
/etc
/bin
/tmp

Примітка по cd -: Джокеру в відповіді допомогло проілюструвати , як cd -не використовує $ DIRSTACK масиву (він використовує $ OLDPW змінний), так що cd -не впливає на $ DIRSTACK шляху стека на основі своп повинен. Щоб виправити це, ось проста функція swap на основі $ DIRSTACK :

scd() { { pushd ${DIRSTACK[1]} ; popd -n +2 ; } > /dev/null ; }

Тест:

dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs

Вихід:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp

Моє розчарування полягає в тому, що я хочу помістити елементи в стек і тримати їх там, поки я не вирішу очистити стек. Таким чином я можу штовхати, штовхати, штовхати, а потім проїжджати через кожний із трьох дрів, якщо потрібно. Скажімо, наприклад, мені потрібно переходити між трьома каталогами так, ніби вони схожі на вкладки браузера, і йти туди-назад, поки я не закрию вкладку. Це вирішує це в командному рядку?
Воломійка

5
Так, я вірю, що це так, спробуйте. Щоб видалити верхній предмет, зробіть popd, щоб видалити його, не змінюючи брусок, зробіть popd -n. Щоб очистити стек, зробіть dirs -c. Шкода, що баш дизайнери закопували такі корисні функції в неінтуїтивний синтаксис. Дивіться man bashпід pushdі dirsт. Д.
agc

Працює! І було ясно, як грязь у документах. Мені подобається простота цього, тепер, коли я знаю техніку.
Воломійка

13

Я пропоную вам встановити fasd . Це дає можливість швидко перейти до будь-якого каталогу, в якому ви вже були, ввівши лише невелику частину його імені.

Приклад: якщо ви відвідали /home/someName/scripts/, ви можете перейти туди, просто ввівши, z scrнаприклад. Це набагато зручніше, ніж запам'ятовувати впорядкування в стеку історії чи щось подібне.


10

Коли - cdто, Bash зберігає старий робочий каталог змінної оточення $OLDPWD.

Ви можете переключитися назад в той каталог, за допомогою cd -якого еквівалентно cd "$OLDPWD".

Ви можете підстрибувати назад і назад між такими каталогами:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$

6

Я написав сценарій xyzzyдля цього:

#!/bin/bash

i="$1"
i=$((${i//[^0-9]/}))
i="$(($i-1+0))"

b="$2"
b=$((${b//[^0-9]/}))
b="$(($b-1+0))"

if [ -z "$XYZZY_INDEX" ]; then
    XYZZY_INDEX="$((-1))"
fi

if [ ! -f "/tmp/xyzzy.list" ]; then
    touch /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
fi
readarray -t MYLIST < /tmp/xyzzy.list

showHelp(){
read -r -d '' MYHELP <<'EOB'
xyzzy 1.0

A command for manipulating escape routes from grues. Otherwise known as a useful system admin
tool for storing current directories and cycling through them rapidly. You'll wonder why this
wasn't created many moons ago.

Usage: xyzzy [options]

help/-h/--help      Show the help.

this/-t/--this      Store the current directory in /tmp/xyzzy.list

begone/-b/--begone  Clear the /tmp/xyzzy.list file. However, succeed with a number and
            it clears just that item from the stored list.

show/-s/--show      Show the list of stored directories from /tmp/xyzzy.list

. #         Use a number to 'cd' to that directory item in the stored list. This syntax is odd:

            . xyzzy 2

            ...would change to the second directory in the list

. [no options]      Use the command alone and it cd cycles through the next item in the stored 
            list, repeating to the top when it gets to the bottom. The dot and space before xyzzy
            is required in order for the command to run in the current shell and not a subshell:

            . xyzzy

Note that you can avoid the odd dot syntax by adding this to your ~/.bashrc file:

  alias xyzzy=". xyzzy"

and then you can do "xyzzy" to cycle through directories, or "xyzzy {number}" to go to a
specific one.

May you never encounter another grue.

Copyright (c) 2016, Mike McKee <https://github.com/volomike>
EOB
    echo -e "$MYHELP\n"
}

storeThis(){
    echo -e "With a stroke of your wand, you magically created the new escape route: $PWD"
    echo "$PWD" >> /tmp/xyzzy.list
    chmod a+rw /tmp/xyzzy.list
}

begoneList(){
    if [[ "$b" == "-1" ]]; then
        echo "POOF! Your escape routes are gone. We bless your soul from the ever-present grues!"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
    else
        echo -n "Waving your wand in the dark, you successfully manage to remove one of your escape routes: "
        echo "${MYLIST[${b}]}"
        >/tmp/xyzzy.list
        chmod a+rw /tmp/xyzzy.list
        for x in "${MYLIST[@]}"; do
            if [[ ! "$x" == "${MYLIST[${b}]}" ]]; then
                echo "$x" >> /tmp/xyzzy.list
            fi
        done
    fi
}

showList(){
    echo -e "These are your escape routes:\n"
    cat /tmp/xyzzy.list
}

cycleNext(){
    MAXLINES=${#MYLIST[@]}
    XYZZY_INDEX=$((XYZZY_INDEX+1))
    if [[ $XYZZY_INDEX > $(($MAXLINES - 1)) ]]; then
        XYZZY_INDEX=0
    fi
    MYLINE="${MYLIST[${XYZZY_INDEX}]}"
    cd "$MYLINE";
}

switchDir(){
    MYLINE="${MYLIST[${i}]}"
    cd "$MYLINE";
}

if [[ "$@" == "" ]];
then
    cycleNext
fi;

while [[ "$@" > 0 ]]; do case $1 in
    help) showHelp;;
    --help) showHelp;;
    -h) showHelp;;
    show) showList;;
    -s) showList;;
    --show) showList;;
    list) showList;;
    this) storeThis;;
    --this) storeThis;;
    -t) storeThis;;
    begone) begoneList;;
    --begone) begoneList;;
    *) switchDir;;
    esac; shift
done

export XYZZY_INDEX

Я використовую це для копіювання в /usr/binпапку, а потім chmod a+xу неї. Потім я редагую свій ~/.bashrcфайл кореневого та облікового запису користувача, щоб включати ці рядки внизу:

alias xyzzy='. xyzzy'
alias xy='. xyzzy'

'Xy' - це скорочена форма команди для швидшого введення тексту.

Тоді я можу зберігати поточний каталог у списку за допомогою ...

xyzzy this

... і повторіть по мірі необхідності. Після заповнення цього списку потрібними мені каталогами вони залишаються там, поки я не перезавантажую комп'ютер, тому що тоді / tmp знову очищається. Потім я можу набрати ...

xyzzy show

... перелічити поточно збережені каталоги. Для того, щоб перейти до каталогу, у мене є два варіанти. Один із варіантів - вказати шлях за індексом (а це індекс на основі 1) так:

xyzzy 2

... що переключиться на каталог, який є другим пунктом у списку. Або я можу залишити номер індексу і просто зробити:

xyzzy

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

xyzzy help

Звичайно, працювати веселіше з дурними ехо-заявами, які я додав.

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


2
+1 Я почав грати з цим. Це приємно, але, здається, виходить з ладу, якщо ще не додано каталогів, а ви вводите лише ксизи. Потрібен ще один тест для MAXLINES -eq 0 у cyclenext ().
Джо

5

Я використовую невеликий скрипт під назвою z [link] , який також може зацікавити, хоча він не робить саме те, про що ви просили.

NAME
       z - jump around

SYNOPSIS
       z [-chlrtx] [regex1 regex2 ... regexn]

AVAILABILITY
       bash, zsh

DESCRIPTION
       Tracks your most used directories, based on 'frecency'.

       After  a  short  learning  phase, z will take you to the most 'frecent'
       directory that matches ALL of the regexes given on the command line, in
       order.

       For example, z foo bar would match /foo/bar but not /bar/foo.

Можливо, я щось пропустив, але де я можу знайти сам сценарій z?
Джо

Вибачте, посилання було на z. Відредагуйте, щоб полегшити їх перегляд.
Грайфер

5

Є також cd_funcвід Петра Маринова, це в основному cdісторія до 10 записів: http://linuxgazette.net/109/misc/marinov/acd_func.html

# do ". acd_func.sh"
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain

cd_func ()
{
  local x2 the_new_dir adir index
  local -i cnt

  if [[ $1 ==  "--" ]]; then
    dirs -v
    return 0
  fi

  the_new_dir=$1
  [[ -z $1 ]] && the_new_dir=$HOME

  if [[ ${the_new_dir:0:1} == '-' ]]; then
    #
    # Extract dir N from dirs
    index=${the_new_dir:1}
    [[ -z $index ]] && index=1
    adir=$(dirs +$index)
    [[ -z $adir ]] && return 1
    the_new_dir=$adir
  fi

  #
  # '~' has to be substituted by ${HOME}
  [[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"

  #
  # Now change to the new dir and add to the top of the stack
  pushd "${the_new_dir}" > /dev/null
  [[ $? -ne 0 ]] && return 1
  the_new_dir=$(pwd)

  #
  # Trim down everything beyond 11th entry
  popd -n +11 2>/dev/null 1>/dev/null

  #
  # Remove any other occurence of this dir, skipping the top of the stack
  for ((cnt=1; cnt <= 10; cnt++)); do
    x2=$(dirs +${cnt} 2>/dev/null)
    [[ $? -ne 0 ]] && return 0
    [[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
    if [[ "${x2}" == "${the_new_dir}" ]]; then
      popd -n +$cnt 2>/dev/null 1>/dev/null
      cnt=cnt-1
    fi
  done

  return 0
}

alias cd=cd_func

if [[ $BASH_VERSION > "2.05a" ]]; then
  # ctrl+w shows the menu
  bind -x "\"\C-w\":cd_func -- ;"
fi

Простір використовуйте cd --для показу списку останніх до 10 каталогів, до яких ви cdредагували, та cd -N(де Nіндекс запису), щоб перейти туди.


4

Я в основному використовую ZSH з профілем oh-my-zsh . Ви можете ввести в термінал наступну відповідність:

# cd /ho

Тоді ви можете просто скористатися стрілками (вгору та вниз), щоб пройти всю історію оболонок, яка показує лише ті записи, які починаються з символів вище. Так, наприклад, якщо ви зайшли /home/morfik/Desktop/і /home/morfik/something/ви можете дуже швидко перемикатися між каталогами. Не має значення, скільки записів у історії оболонки у вас є, але коли їх багато, просто використовуйте кращий вираз, тобто cd /home/morfтут натискайте стрілки вгору / вниз на клавіатурі.

Існує також інший спосіб досягти рішення. У цьому випадку вам доведеться використовувати tmux і FZF . Тоді ви просто зробите гарячу клавішу, наприклад, ctrl-r, і коли ви натиснете її, ваше поточне вікно буде розділене, і ви побачите це:

введіть тут опис зображення

Тепер ви можете використовувати вирази для пошуку списку. Я просто набрав текст ^cd /media, який повертає лише записи, які починаються з фрази. Звичайно, ви можете просто ввести, 'cd 'homeщоб відповідати команді, а також все ім'я каталогу (не шлях, а лише ім'я):

введіть тут опис зображення


4

Ви можете досягти цього за допомогою купки псевдонімів у своєму ~/.bashrc(або еквіваленті)

Основна мета - майже мінімальний набір тексту (наприклад, d5переходи до каталогу № 5 в пулі) для переключення між каталогами в пулі. Також ми хочемо спростити додавання / видалення каталогів до / з пулу:

alias pd=pushd
alias po=popd
alias d='dirs -v'
alias d0=d
alias d1='pd +1'
alias d2='pd +2'
alias d3='pd +3'
alias d4='pd +4'
alias d5='pd +5'
alias d6='pd +6'
alias d7='pd +7'
alias d8='pd +8'
alias d9='pd +9'
alias d10='pd +10'
# -- feel free to add more aliases if your typical dir pool is larger than 10

Тепер кожного разу, коли ви натискаєте на каталог на стек, він додається до нумерованого пулу в позиції 0 (поточний dir), і ви можете стрибати (перемикати каталоги), використовуючи дуже мало набравши ( d<N>), і ви можете переглядати нумерований поточний пул у будь-якому час, просто набравши текст d.

Кілька прикладів використання цих псевдонімів:

Відобразити нумерований dir-pool, (поточний dir - це № 0)

$ d
 0  /tmp
 1  /
 2  /usr

Перемикатися між дровами: використовувати d<N>

$ d2
$ pwd
/usr

Додайте новий каталог до пулу

$ pd /var/log
$ d
 0  /var/log
 1  /usr
 2  /tmp
 3  /

Перестрибніть ще кілька:

$ d3
$ pwd
/

$ d3
$ pwd
/tmp

$ d
 0  /tmp
 1  /
 2  /var/log
 3  /usr

Вийміть / висуньте верхній (поточний) дір із басейну

$ po
$ d
 0  /
 1  /var/log
 2  /usr

2

Якщо у вас встановлений iselect , ви можете зробити щось подібне:

$ alias dirselect='cd $(iselect -a $(dirs -l -p | sort -u))'
$ dirselect

Це дасть вам повне екранне інтерактивне меню, орієнтоване стрілкою, для вибору каталогу, cdдо якого.

Якщо ви не використовували pushdв поточному сеансі оболонки, список каталогів у меню починається лише одним записом, вашим поточним каталогом. Якщо є лише один запис, цей dirselectпсевдонім буде просто cdдля нього без екрана меню, тому він фактично нічого не робить (крім запобігання cd -робити щось корисне)

Щоб додати до каталогу новий каталог, використовуйте pushd dir(або pushd -n dirдодавайте dir одночасно, не входячи cdв нього)

Ви можете попередньо заповнити pushdстек, зробивши щось подібне у своєму .bashrcабо ~/.bash_profile:

for d in /var/tmp /tmp /path/to/somewhere/interesting ; do 
  pushd -n "$d" > /dev/null
done

Ви можете видалити записи за допомогою popdабо popd -n.

Побачити help pushd , help popdі help dirsв bash для отримання додаткової інформації. І, звичайно ж , man iselect.

До речі, iselect ймовірно, доступний заздалегідь упакований для вашого дистрибутива. Це для Debian і Ubuntu тощо, і, мабуть, і для інших.


2

Якщо у вас є 5 або 10 каталогів, ви багато використовуєте, і не обов’язково дбаєте про нещодавно використані 5 або 10 каталогів, налаштуйте кілька псевдонімів команд, наприклад

alias cdw="cd /var/www/html" 

І тому, коли я хочу зайти в каталог домашньої сторінки Apache, я просто набираю, cdwяк відповів у " Еквівалент псевдоніма" за символічне посилання? .


2

Я використовую стрибок для швидкої зміни робочого каталогу.

Щоб додати поточний каталог:

jump -a [bookmark-name]

Щоб перерахувати всі ваші закладки:

jump -l

наприклад:

------------------------------------------------------------------
 Bookmark    Path                                                 
------------------------------------------------------------------
 reports     ~/mydir/documents/reports
 projects    ~/documents/projects
 dl          ~/Downloads                     
------------------------------------------------------------------

Тепер ви можете легко перейти до іншого каталогу:

jump reports

Він підтримує автодоповнення для bash та zsh.


Редагувати (у відповідь на @Joe): двійковий файл jump-binзберігається в /usr/local/bin, і за допомогою сценарію інтеграції bash (на моєму ПК, розташованому в /var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driver) він створює функцію bash, jumpяка викликає jump-bin.


Де живе команда стрибок? У мене його немає і не відразу бачу, де його взяти.
Джо

2

Я використовую aliasдля навігації. Якщо у вас є кілька каталогів, до яких часто звертаєтесь, просто встановіть псевдоніми. Наприклад,

alias e='cd /etc'
alias h='cd /home'
alias al='cd /var/log/apache2/'

Тоді просто

e 

приведе вас до /etc.

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