Cách dòng lệnh nhanh để chuyển giữa nhiều thư mục để quản trị hệ thống là gì?


46

Cách dòng lệnh nhanh để chuyển giữa nhiều thư mục để quản trị hệ thống là gì? Ý tôi là, tôi có thể sử dụng pushd .popdchuyển đổi, nhưng nếu tôi muốn lưu trữ bội số và xoay vòng qua chúng, thay vì bật chúng vĩnh viễn khỏi đáy ngăn xếp thì sao?


$CDPATHcó lẽ?
roaima

6
oh my - tôi vừa tìm hiểu về cd -sau khi googling xúi giục từ câu hỏi này.
thuyền - Phục hồi Monica

@Nacht: Làm thế nào bạn điều hướng cấu trúc tập tin trước ??
loneboat

1
Đã làm cdmọi nơi bằng tay. Đã đau. Được sử dụng hoàn thành tự động với phím tab, mặc dù.
Volomike

1
Có lẽ bạn muốn cho za thử . Vô cùng tiện dụng khi bạn nhảy xung quanh rất nhiều trong cùng một vài thư mục.
Rolf

Câu trả lời:


28

Sử dụng pushdvà sau đó là tên đặc biệt cho các thư mục trong đống thư mục của bạn: ~1, ~2vv

Thí dụ:

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 $ 

Cách hiệu quả nhất để sử dụng pushdtheo cách này là tải lên danh sách thư mục của bạn, sau đó thêm một thư mục nữa vào thư mục hiện tại của bạn và sau đó bạn có thể nhảy giữa các số tĩnh mà không ảnh hưởng đến vị trí của các thư mục trong ngăn xếp của bạn.


Cũng đáng lưu ý rằng cd -sẽ đưa bạn đến thư mục cuối cùng bạn đã ở. Vì vậy, sẽ cd ~-.

Ưu điểm của việc ~-trên chỉ --là cụ thể cho cd, trong khi ~-được mở rộng bởi shell của bạn cùng một cách mà ~1, ~2vv đang có. Điều này rất hữu ích khi sao chép một tập tin giữa các đường dẫn thư mục rất dài; ví dụ:

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

Trên đây là tương đương với:

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

1
Cũng có thể sử dụngcd -
Volomike

cd -hoạt động như một Forth DROP DUP, ví dụ nếu một bắt đầu bằng trong thư mục a , với ngăn xếp abcd , thì cd -thay đổi ngăn xếp thành bbcd . Có lẽ đó là một bashlỗi tuy nhiên, vì một giây cd -thay đổi ngăn xếp trở lại abcd . Từ đó, chúng ta có thể suy ra rằng cd -sử dụng một số cấu trúc dữ liệu riêng biệt để lưu trữ thư mục trước đó, ngoài việc thay đổi ngăn xếp.
agc

3
@agc, cd -sử dụng $OLDPWDvà không có gì khác.
tự đại diện

Vì vậy, có thể cd -là tính năng bash trước đó , sau đó họ đã thêm một ngăn xếp, nhưng sợ phá vỡ mã cũ hơn họ muốn một thiết kế đơn giản hơn. Sửa lỗi trước đó, cd -hoạt động giống như Forth OLDPWD @ SWAP OLDPWD ! DUP . Không giống như cd foo, cd -in tên của thư mục tráo đổi.
agc

Hoặc luôn luôn có trình bao bọc tương tác (các câu trả lời khác cho câu hỏi đó bao gồm tự động bật, v.v.).
Vô dụng

42

bashĐược xây dựng pushdvới +-các tùy chọn có thể xoay ngăn xếp thư mục. Cú pháp có thể hơi khó hiểu, có lẽ bởi vì ngăn xếp đó là một mảng không có cơ sở. Các hàm bao bọc đơn giản này quay vòng qua ngăn xếp thư mục:

# 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 ; }

Kiểm tra: thiết lập một chồng gồm bốn thư mục.

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

Bây giờ / tmpthư mục hiện tại và ngăn xếp trông như sau:

/tmp /bin /etc /home

Thay đổi thư mục tiếp theo trong ngăn xếp, (và hiển thị nó), bốn lần:

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

Đầu ra:

/bin
/etc
/home
/tmp

Thay đổi thư mục trước trong ngăn xếp, (và hiển thị nó), bốn lần:

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

Đầu ra:

/home
/etc
/bin
/tmp

Một lưu ý về cd -: Câu trả lời của Wildcard đã giúp minh họa cách cd -không sử dụng mảng $ DIRSTACK , (nó sử dụng biến $ OLDPW ), do đó cd -không ảnh hưởng đến $ DIRSTACK theo cách trao đổi dựa trên ngăn xếp. Để sửa lỗi đó, đây là một hàm hoán đổi dựa trên $ DIRSTACK đơn giản :

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

Kiểm tra:

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

Đầu ra:

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

Sự thất vọng của tôi là tôi muốn đặt các vật phẩm vào ngăn xếp và giữ chúng ở đó cho đến khi tôi chọn xóa ngăn xếp. Bằng cách đó, tôi có thể đẩy, đẩy, đẩy, sau đó quay vòng qua ba đường dẫn khi cần thiết. Ví dụ, tôi cần phải lật giữa ba thư mục như thể chúng giống như các tab trình duyệt và quay lại, cho đến khi tôi đóng một tab. Liệu điều này giải quyết điều này theo một cách dòng lệnh?
Volomike

5
Vâng, tôi tin rằng nó làm, hãy thử nó. Để loại bỏ các mục hàng đầu, làm popd, để loại bỏ nó mà không thay đổi dirs, làm popd -n. Để xóa ngăn xếp làm dirs -c. Quá tệ, các nhà thiết kế bash đã chôn các hàm hữu ích như vậy theo cú pháp không trực quan. Xem man bashbên dưới pushd, dirsv.v.
agc

Làm! Và rõ ràng như bùn trong các tài liệu. Tôi thích sự đơn giản của nó, bây giờ tôi đã biết kỹ thuật.
Volomike

13

Tôi đề nghị bạn cài đặt fasd . Nó cung cấp cho bạn khả năng nhanh chóng chuyển đến bất kỳ thư mục nào bạn đã tham gia bằng cách chỉ nhập một phần nhỏ tên của nó.

Ví dụ: nếu bạn đã truy cập /home/someName/scripts/, bạn có thể nhảy đến đó chỉ bằng cách nhập z scrví dụ. Thật tiện lợi hơn khi ghi nhớ thứ tự trong ngăn xếp lịch sử hoặc bất cứ thứ gì tương tự.


10

Khi bạn cdở đâu đó, Bash lưu trữ thư mục làm việc cũ một biến môi trường , $OLDPWD.

Bạn có thể chuyển trở lại thư mục cd -đó, tương đương với cd "$OLDPWD".

Bạn có thể nảy qua lại giữa các thư mục như vậy:

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

6

Tôi đã viết một kịch bản có tên xyzzyđể làm điều này:

#!/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

Cách tôi sử dụng là sao chép vào /usr/binthư mục và sau đó chmod a+xvào nó. Sau đó, tôi chỉnh sửa ~/.bashrctệp gốc và tài khoản người dùng của mình để bao gồm các dòng này ở dưới cùng:

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

'Xy' là một dạng rút gọn của lệnh để gõ nhanh hơn.

Sau đó, tôi có thể lưu trữ thư mục hiện tại trong danh sách với ...

xyzzy this

... Và lặp lại khi cần thiết. Khi tôi điền danh sách này vào các thư mục tôi cần, chúng sẽ ở đó cho đến khi tôi khởi động lại máy tính vì đó là khi / tmp bị xóa lần nữa. Sau đó tôi có thể gõ ...

xyzzy show

... Để liệt kê các thư mục hiện đang lưu. Để chuyển sang một thư mục, tôi có hai lựa chọn. Một tùy chọn là chỉ định đường dẫn theo chỉ mục (và đó là chỉ mục dựa trên 1) như vậy:

xyzzy 2

... sẽ chuyển sang thư mục đó là mục thứ hai trong danh sách. Hoặc, tôi có thể bỏ số chỉ mục và chỉ cần làm:

xyzzy

... để có vòng lặp qua từng thư mục mà tôi cần. Để biết thêm các lệnh bạn có thể làm, gõ:

xyzzy help

Tất nhiên, công việc thú vị hơn với những câu nói ngớ ngẩn mà tôi đã thêm vào.

Lưu ý rằng xyzzy là một tham chiếu đến cuộc phiêu lưu văn bản Hang động Collosal , trong đó việc nhập xyzzy sẽ cho phép bạn chuyển đổi giữa hai phòng trong trò chơi để tránh các mối đe dọa.


2
+1 Tôi bắt đầu chơi với cái này. Thật tuyệt, nhưng dường như thất bại nếu chưa có thư mục nào được thêm vào và bạn chỉ nhập xyzzy. Cần thêm một bài kiểm tra cho MAXLINES -eq 0 trong cyclenext ().
Joe

5

Tôi sử dụng một tập lệnh nhỏ gọi là z [link] , cũng có thể được quan tâm, mặc dù nó không thực hiện chính xác những gì bạn yêu cầu.

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.

Có lẽ tôi đã bỏ lỡ điều gì đó, nhưng tôi tìm thấy tập lệnh z ở đâu?
Joe

Xin lỗi, liên kết là trên z. Sẽ chỉnh sửa để dễ nhìn hơn.
Graodes

5

Ngoài ra còn có cd_functừ Petar Marinov, về cơ bản nó cdcó lịch sử lên tới 10 mục: 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

Siimply sử dụng cd --để hiển thị một danh sách quá khứ lên tới 10 thư mục bạn đã chỉnh cdsửa và cd -N(nơi Nchỉ mục của mục nhập) đi đến đó.


4

Tôi chủ yếu sử dụng ZSH với hồ sơ oh-my-zsh . Bạn có thể nhập vào một thiết bị đầu cuối phù hợp sau đây:

# cd /ho

Sau đó, bạn có thể chỉ cần sử dụng mũi tên (lên và xuống) để đi qua tất cả lịch sử shell chỉ hiển thị những mục bắt đầu bằng các ký tự ở trên. Vì vậy, ví dụ, nếu bạn đã đến /home/morfik/Desktop//home/morfik/something/, bạn có thể chuyển đổi giữa các thư mục rất nhanh. Không quan trọng bạn có bao nhiêu mục trong lịch sử shell, nhưng khi bạn có nhiều mục, chỉ cần sử dụng một biểu thức tốt hơn, tức là cd /home/morfvà ở đây nhấn mũi tên lên / xuống trên bàn phím của bạn.

Cũng có một cách khác để đạt được giải pháp. Trong trường hợp này, bạn phải sử dụng tmuxFZF . Sau đó, bạn chỉ cần tạo một phím nóng, ví dụ ctrl-r và khi bạn nhấn nó, cửa sổ hiện tại của bạn sẽ được chia và bạn sẽ thấy điều này:

nhập mô tả hình ảnh ở đây

Bây giờ bạn có thể sử dụng biểu thức để tìm kiếm danh sách. Tôi vừa gõ ^cd /media, chỉ trả về các mục bắt đầu bằng cụm từ. Tất nhiên, bạn chỉ có thể gõ 'cd 'homeđể khớp lệnh và cả tên thư mục (không phải đường dẫn, chỉ tên):

nhập mô tả hình ảnh ở đây


4

Bạn có thể đạt được điều này với một loạt các bí danh trong ~/.bashrc(hoặc tương đương)

Mục tiêu chính là gõ gần như tối thiểu (ví dụ: d5nhảy đến thư mục số 5 trong nhóm) để chuyển giữa các thư mục trong nhóm. Ngoài ra, chúng tôi muốn làm cho nó dễ dàng để thêm / xóa thư mục đến / từ nhóm:

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

Bây giờ mỗi khi bạn đẩy một thư mục trên ngăn xếp, nó sẽ được thêm vào nhóm được đánh số ở vị trí 0 (thư mục hiện tại) và bạn có thể nhảy xung quanh (chuyển thư mục) bằng cách gõ rất ít ( d<N>) và bạn có thể xem nhóm hiện tại được đánh số của mình thời gian chỉ bằng cách gõ d.

Một vài ví dụ về việc sử dụng các bí danh này:

Hiển thị nhóm thư mục được đánh số, (thư mục hiện tại là # 0)

$ d
 0  /tmp
 1  /
 2  /usr

Chuyển đổi giữa các thư mục: sử dụng d<N>

$ d2
$ pwd
/usr

Thêm một thư mục mới vào nhóm

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

Nhảy qua một số chi tiết:

$ d3
$ pwd
/

$ d3
$ pwd
/tmp

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

Xóa / bật thư mục (hiện tại) hàng đầu khỏi nhóm

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

2

Nếu bạn đã iselect cài đặt, bạn có thể làm một cái gì đó như thế này:

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

Điều này sẽ cung cấp cho bạn một menu điều hướng phím mũi tên tương tác toàn màn hình dựa trên ncurses để chọn một thư cdmục.

Nếu bạn chưa sử dụng pushdtrong phiên shell hiện tại, danh sách các thư mục trong menu sẽ bắt đầu chỉ với một mục, thư mục hiện tại của bạn. Nếu chỉ có một mục nhập, dirselectbí danh này sẽ chỉ hiển cdthị mà không có màn hình menu, vì vậy nó thực sự không có gì (ngoại trừ ngăn không cd -làm gì hữu ích)

Để thêm một thư mục mới vào danh sách, hãy sử dụng pushd dir(hoặc pushd -n dirđể thêm một thư mục mà không cần vào thư mục cdđó cùng một lúc)

Bạn có thể điền trước pushdngăn xếp bằng cách thực hiện một số thứ như sau trong .bashrchoặc ~/.bash_profile:

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

Bạn có thể xóa các mục với popdhoặc popd -n.

Xem help pushd, help popdhelp dirstrong bash để biết thêm. Và, tất nhiên , man iselect.

BTW, iselectcó thể có sẵn đóng gói sẵn cho bản phân phối của bạn. Nó dành cho Debian và Ubuntu, v.v. và có lẽ cho cả những người khác nữa.


2

Nếu bạn có 5 hoặc 10 thư mục bạn sử dụng nhiều và không nhất thiết phải quan tâm đến 5 hoặc 10 thư mục được sử dụng gần đây , hãy thiết lập một số bí danh lệnh như

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

Và khi tôi muốn vào thư mục trang chủ Apache, tôi chỉ cần gõ cdwnhư tôi đã trả lời trong Tương đương bí danh cho một liên kết tượng trưng? .


2

Tôi đang sử dụng jump để nhanh chóng thay đổi thư mục làm việc.

Để thêm thư mục hiện tại:

jump -a [bookmark-name]

Để liệt kê tất cả các dấu trang của bạn:

jump -l

ví dụ:

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

Bây giờ bạn có thể dễ dàng chuyển sang thư mục khác:

jump reports

Nó hỗ trợ tự động hoàn thành cho bash và zsh.


Chỉnh sửa (để phản hồi @Joe): tệp nhị phân jump-binđược lưu trữ /usr/local/binvà với tập lệnh tích hợp bash (trong PC của tôi nằm ở /var/lib/gems/1.9.1/gems/jump-0.4.1/bash_integration/shell_driverđó), nó tạo ra một hàm bash jumpgọi jump-bin.


Lệnh nhảy sống ở đâu? Tôi không có nó và không thấy ngay nơi để lấy nó.
Joe

2

Tôi sử dụng aliasđể điều hướng. Nếu bạn có một vài thư mục thường xuyên được truy cập, thì chỉ cần đặt bí danh. Ví dụ,

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

Sau đó, đơn giản

e 

sẽ đưa bạn đến /etc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.