简体   繁体   中英

Bash alias utilizing the command inputs

I want to create a bash alias to do the following:

Assume I am at the following path:

/dir1/dir2/dir3/...../dirN

I want to go up to dir3 directly without using cd .. . I will just write cdd dir3 and it should go directly to /dir1/dir2/dir3 . cdd is my alias name.

I wrote the following alias, but it doesn't work:

alias cdd='export newDir=$1; export myPath=`pwd | sed "s/\/$newDir\/.*/\/$newDir/"`; cd $myPath'

Simply it should get the current full path, then remove anything after the new destination directory, then cd to this new path

The problem with my command is that $1 doesn't get my input to the command cdd

This is a slightly simpler function that I think achieves what you're trying to do:

cdd() { cd ${PWD/$1*}$1; }

Explanation:

${PWD/$1*}$1 takes the current working directory and strips off everything after the string passed to it (the target directory), then adds that string back. This is then used as an argument for cd . I didn't bother adding any error handling as cd will take care of that itself.

Example:

[atticus:pgl]:~/tmp/a/b/c/d/e/f $ cdd b
[atticus:pgl]:~/tmp/a/b $

It's a little ugly, but it works.

Here's a function - which you could place in your shell profile - which does what you want; note that in addition to directory names it also supports levels (eg, cdd 2 to go up 2 levels in the hierarchy); just using cdd will move up to the parent directory.

Also note that matching is case-INsensitive.

The code is taken from " How can I replace a command line argument with tab completion? ", where you'll also find a way to add complementary tab-completion for ancestral directory names.

    cdd () 
    { 
        local dir='../';
        [[ "$1" == '-h' || "$1" == '--help' ]] && { 
            echo -e "usage:
        $FUNCNAME [n]
        $FUNCNAME dirname
      Moves up N levels in the path to the current working directory, 1 by default.
      If DIRNAME is given, it must be the full name of an ancestral directory (case does not matter).
      If there are multiple matches, the one *lowest* in the hierarchy is changed to." && return 0
        };
        if [[ -n "$1" ]]; then
            if [[ $1 =~ ^[0-9]+$ ]]; then
                local strpath=$( printf "%${1}s" );
                dir=${strpath// /$dir};
            else
                if [[ $1 =~ ^/ ]]; then
                    dir=$1;
                else
                    local wdLower=$(echo -n "$PWD" | tr '[:upper:]' '[:lower:]');
                    local tokenLower=$(echo -n "$1" | tr '[:upper:]' '[:lower:]');
                    local newParentDirLower=${wdLower%/$tokenLower/*};
                    [[ "$newParentDirLower" == "$wdLower" ]] && { 
                        echo "$FUNCNAME: No ancestral directory named '$1' found." 1>&2;
                        return 1
                    };
                    local targetDirPathLength=$(( ${#newParentDirLower} + 1 + ${#tokenLower} ));
                    dir=${PWD:0:$targetDirPathLength};
                fi;
            fi;
        fi;
        pushd "$dir" > /dev/null
    }

I agree with mklement0, this should be a function. But a simpler one.

Add this to your .bashrc :

cdd () {
  newDir="${PWD%%$1*}$1"
  if [ ! -d "$newDir" ]; then
    echo "cdd: $1: No such file or directory" >&2
    return 1
  fi
  cd "${newDir}"
}

Note that if $1 (your search string) appears more than once in the path, this function will prefer the first one. Note also that if $1 is a substring of a path, it will not be found. For example:

[ghoti@pc ~]$ mkdir -p /tmp/foo/bar/baz/foo/one
[ghoti@pc ~]$ cd /tmp/foo/bar/baz/foo/one
[ghoti@pc /tmp/foo/bar/baz/foo/one]$ cdd foo
[ghoti@pc /tmp/foo]$ cd -
/tmp/foo/bar/baz/foo/one
[ghoti@pc /tmp/foo/bar/baz/foo/one]$ cdd fo
cdd: fo: No such file or directory

If you'd like to include the functionality of going up 2 levels by running cdd 2 , this might work:

cdd () {
  newDir="${PWD%%$1*}$1"
  if [ "$1" -gt 0 -a "$1" = "${1%%.*}" -a ! -d "$1" ]; then
    newDir=""
    for _ in $(seq 1 $1); do
      newDir="../${newDir}"
    done
    cd $newDir
    return 0
  elif [ ! -d "$newDir" ]; then
    echo "cdd: $1: No such file or directory" >&2
    return 1
  fi
  cd "${newDir}"
}

The long if statement verifies that you've supplied an integer that is not itself a directory. We build a new $newDir so that you can cd - to get back to your original location if you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM