我如何cd到上一个/下一个兄弟目录?


10

我经常有这样的项目目录布局

project
`-- component-a
|   `-- files...
`-- component-b
|   `-- files...
`-- component-c
    `-- files...

我通常将在其中一个component目录中工作,因为这是文件所在的位置。然后,当我返回外壳程序时,通常只需要移至同级目录,尤其是当我需要对每个组件进行一些不可编写脚本的更改时。在这些情况下,我什至都不关心我将要使用的上一个兄弟目录或下一个兄弟目录。

我可以定义一个命令prev还是next将其简单cd地带入上一个目录或下一个目录(按字母或其他字母)?因为cd ../com<TAB><Arrow keys>一直以来打字都有些陈旧。

Answers:


8

不要使用其他答案中的commandlinefu解决方案:这是不安全¹且效率低下的。²相反,如果使用bash,则只需使用以下功能。为了使它们持久,请将它们放入您的中.bashrc。请注意,我使用全局顺序是因为它是内置的并且很容易。通常,在大多数语言环境中,全局顺序都是按字母顺序排列的。如果没有下一个或上一个目录,您将收到一条错误消息。特别是,如果您尝试在根目录nextprev中尝试该错误,则会看到该错误/

## bash and zsh only!
# functions to cd to the next or previous sibling directory, in glob order

prev () {
    # default to current directory if no previous
    local prevdir="./"
    local cwd=${PWD##*/}
    if [[ -z $cwd ]]; then
        # $PWD must be /
        echo 'No previous directory.' >&2
        return 1
    fi
    for x in ../*/; do
        if [[ ${x#../} == ${cwd}/ ]]; then
            # found cwd
            if [[ $prevdir == ./ ]]; then
                echo 'No previous directory.' >&2
                return 1
            fi
            cd "$prevdir"
            return
        fi
        if [[ -d $x ]]; then
            prevdir=$x
        fi
    done
    # Should never get here.
    echo 'Directory not changed.' >&2
    return 1
}

next () {
    local foundcwd=
    local cwd=${PWD##*/}
    if [[ -z $cwd ]]; then
        # $PWD must be /
        echo 'No next directory.' >&2
        return 1
    fi
    for x in ../*/; do
        if [[ -n $foundcwd ]]; then
            if [[ -d $x ]]; then
                cd "$x"
                return
            fi
        elif [[ ${x#../} == ${cwd}/ ]]; then
            foundcwd=1
        fi
    done
    echo 'No next directory.' >&2
    return 1
}

¹它不能处理所有可能的目录名称。 解析ls输出绝不是安全的

² cd可能不需要非常高效,但是6个过程有点多余。


1
我实际上使用的是zsh,但是如果您将下一个函数的for循环中的第一个测试更改为[[ -n $foundcwd ]]bsh和zsh ,则您的答案同样适用。非常好,感谢您撰写本文。
Esteis 2012年

4

以下功能允许更改为同级目录(bash功能)

function sib() {
    ## sib  search sibling directories 
    ##   prompt for choice (when two or more directories are found, current dir is removed from choices) 
    ##   change to directory after selection 
    local substr=$1
    local curdir=$(pwd)
    local choices=$(find .. -maxdepth 1 -type d -name "*${substr}*" | grep -vE '^..$' | sed -e 's:../::' | grep -vE "^${curdir##*/}$" | sort)
    if [ -z "$choices" ]; then
        echo "Sibling directory not found!"
        return
    fi
    local count=$(echo "$choices" | wc -l)
    if [[ $count -eq 1 ]]; then
        cd ../$choices
        return 
    fi
    select dir in $choices; do
        if [ -n "$dir" ]; then
            cd ../$dir
        fi
        break
    done
}

使用示例:

$ tree
  .
  ├── component-aaa-01
  ├── component-aaa-02
  ├── component-bbb-01
  ├── component-bbb-02
  ├── component-ccc-01
  ├── component-ccc-02
  └── component-ccc-03
  7 directories, 0 files
  $ cd component-aaa-01/
  $ sib bbb-01
  $ pwd
  component-bbb-01
  $ sib bbb
  $ pwd
  component-bbb-02
  $ sib ccc
  1) component-ccc-01
  2) component-ccc-02
  3) component-ccc-03
  #? 3
  $ pwd
  component-ccc-03
  $ sib 01
  1) component-aaa-01
  2) component-bbb-01
  3) component-ccc-01
  #? 2
  $ pwd
  component-bbb-01

非常好。我将jw013的答案保留为被接受的答案,因为我的问题和用例是“我想移至下一个同级,而我不在乎它的名字”。但这也很有用,也很漂亮,所以也要投票。
Esteis 2014年

2

我在commandlinefu.com找到了提示。我将其重新发布到此next处以使其更易于查找,并附有说明和添加的命令。

alias prev='cd ../"$(ls -F .. | grep '/' | grep -B1 -xF "${PWD##*/}/" | head -n 1)"'
alias next='cd ../"$(ls -F .. | grep '/' | grep -A1 -xF "${PWD##*/}/" | tail -n 1)"'

魔术在$(...)块中。它通过以下方式相互传递一些命令:

ls -F .. |   # list items in parent dir; `-F` requests filetype indicators
grep '/' |   # select the directories (written as  `mydir/`)
grep -B1 -xF "${PWD##*/}/" |   # search for the name of the current directory in the output;
                               # print it and the line preceding it
head -n 1    # the first of those two lines contains the name of the previous sibling

2
您找到的命令有很多问题。我已经对其进行了编辑,以更正最严重的错误:将目录名称视为grep模式,并允许其匹配子字符串;并且它对目录名进行了两次外壳扩展(分词和通配符)(总是在变量和命令替换处使用双引号:"$foo""$(foo)")。此外,解析的输出ls是不可靠的,它可能因文件名包含无法打印的字符而失败。
吉尔(Gilles)'所以
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.