在系统管理的多个目录之间切换的快速命令行方式是什么?

Vol*_*ike 47 bash administration shell-script

在系统管理的多个目录之间切换的快速命令行方式是什么?我的意思是,我可以使用pushd .popd来切换,但是如果我想存储倍数并在它们之间循环,而不是永久地将它们从堆栈底部弹出怎么办?

agc*_*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 ; }
Run Code Online (Sandbox Code Playgroud)

测试:设置四个目录的堆栈。

dirs -c   # clear directory stack
cd /home ; pushd /etc ; pushd /bin ; pushd /tmp
Run Code Online (Sandbox Code Playgroud)

现在/tmp是当前目录,堆栈看起来像:

/tmp /bin /etc /home
Run Code Online (Sandbox Code Playgroud)

切换到堆栈中的下一个目录(并显示它),四次:

ncd ; pwd ; ncd ; pwd ; ncd ; pwd ; ncd ; pwd
Run Code Online (Sandbox Code Playgroud)

输出:

/bin
/etc
/home
/tmp
Run Code Online (Sandbox Code Playgroud)

更改到堆栈中的上一个目录(并显示),四次:

pcd ; pwd ; pcd ; pwd ; pcd ; pwd ; pcd ; pwd
Run Code Online (Sandbox Code Playgroud)

输出:

/home
/etc
/bin
/tmp
Run Code Online (Sandbox Code Playgroud)

关于cd -通配符的回答帮助说明了如何cd -不使用$DIRSTACK数组(它使用$OLDPW变量),因此它cd -不会像基于堆栈的交换那样影响$DIRSTACK。为了纠正这个问题,这里有一个简单的基于$DIRSTACK交换函数:

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

测试:

dirs -c; cd /tmp; \
pushd /bin; \
pushd /etc; \
pushd /lib; \
pushd /home; \
scd; dirs; scd; dirs
Run Code Online (Sandbox Code Playgroud)

输出:

/bin /tmp
/etc /bin /tmp
/lib /etc /bin /tmp
/home /lib /etc /bin /tmp
/lib /home /etc /bin /tmp
/home /lib /etc /bin /tmp
Run Code Online (Sandbox Code Playgroud)

  • 是的,我相信确实如此,请尝试一下。要删除顶部项目,请执行`popd`,要在不更改目录的情况下删除它,请执行`popd -n`。要清除堆栈,请执行`dirs -c`。太糟糕了,*bash* 设计者将这些有用的函数隐藏在非直观的语法中。参见`pushd`、`dirs`等下的`man bash`。 (5认同)

Wil*_*ard 30

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 $ 
Run Code Online (Sandbox Code Playgroud)

这种方式最有效的使用pushd方法是加载你的目录列表,然后再添加一个目录作为你的当前目录,然后你就可以在静态数字之间跳转,而不会影响目录在你的堆栈中的位置。


还值得注意的是,cd -它将带您到您所在的最后一个目录。也是 如此cd ~-

的优势,~-经过短短-的是,-特定于cd,而~-扩大你的shell以同样的方式~1~2等都是。在很长的目录路径之间复制文件时,这会派上用场;例如:

cd /very/long/path/to/some/directory/
cd /another/long/path/to/where/the/source/file/is/
cp myfile ~-
Run Code Online (Sandbox Code Playgroud)

以上相当于:

cp /another/long/path/to/where/the/source/file/is/myfile /very/long/path/to/some/directory/
Run Code Online (Sandbox Code Playgroud)

  • @agc,`cd -` 使用 `$OLDPWD` 而没有别的。 (3认同)

kaq*_*qao 13

我建议你安装fasd。它使您能够通过键入其名称的一小部分来快速跳转到您已经进入的任何目录。

示例:如果您访问过/home/someName/scripts/,则只需键入z scr例如即可跳转到那里。记住历史堆栈中的顺序或任何类似的东西更方便。


RJH*_*ter 11

当您在cd某个地方时,Bash 会将旧的工作目录存储为环境变量$OLDPWD.

您可以使用 切换回该目录cd -,相当于cd "$OLDPWD".

您可以像这样在目录之间来回弹跳:

blue$ cd ~/green
green$ cd -
blue$ cd -
green$
Run Code Online (Sandbox Code Playgroud)


Vol*_*ike 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
Run Code Online (Sandbox Code Playgroud)

我使用它的方法是复制到/usr/bin文件夹中,然后chmod a+x在它上面。然后,我编辑我的 root 和用户帐户~/.bashrc文件以在底部包含这些行:

alias xyzzy='. xyzzy'
alias xy='. xyzzy'
Run Code Online (Sandbox Code Playgroud)

'xy' 是命令的缩写形式,用于加快输入速度。

然后,我可以将当​​前目录存储在列表中...

xyzzy this
Run Code Online (Sandbox Code Playgroud)

...并根据需要重复。一旦我用我需要的目录填写了这个列表,它们就会保留在那里,直到我重新启动计算机,因为那时 /tmp 再次被清除。然后我可以输入...

xyzzy show
Run Code Online (Sandbox Code Playgroud)

...列出当前保存的目录。为了切换到一个目录,我有两个选择。一种选择是按索引指定路径(它是一个基于 1 的索引),如下所示:

xyzzy 2
Run Code Online (Sandbox Code Playgroud)

...这将切换到列表中的第二个项目的目录。或者,我可以不使用索引号而只执行以下操作:

xyzzy
Run Code Online (Sandbox Code Playgroud)

...让它根据需要循环遍历每个目录。要获取更多可以执行的命令,请键入:

xyzzy help
Run Code Online (Sandbox Code Playgroud)

当然,使用我添加的愚蠢的 echo 语句,工作会更有趣。

请注意,xyzzy 是对Collosal Cave文本冒险的引用,在其中键入 xyzzy 将让您在游戏中的两个房间之间切换,以避免发生骚乱。

  • +1 我开始玩这个。这很好,但如果尚未添加任何目录并且您只输入 xyzzy,则似乎会失败。需要对 cyclenext() 中的 MAXLINES -eq 0 再进行一项测试。 (2认同)

phk*_*phk 5

也有cd_func来自 Petar Marinov,它基本上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
Run Code Online (Sandbox Code Playgroud)

简单地用于cd --显示过去最多 10 个您访问过的目录的列表,cd并且cd -NN条目的索引在哪里)到那里去。


Gra*_*her 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.
Run Code Online (Sandbox Code Playgroud)