Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I do a lot of work in Magento, and so do a lot of the people I work with, and it gets annoying to have to type:

cd ../../../../../../

To only find you're still a few directories from your root 'httpdocs' folder, so I'm trying to make a script that follows this pseudo-code:

while lowest level directory != httpdocs
    cd ../
end while;

Seems pretty simple, I'm assuming I would have to do some form of grep on checking if the last part of the current working directory is httpdocs, if not just keep going up a level until it's true.

I've been looking at learning bash for this, though it seems like there has to be something out there already that's similar, and the syntax puzzles me to no end.

share|improve this question

5 Answers 5

up vote 4 down vote accepted

This has to be a shell function, not a script, because a script executes in a new shell (and thus can't change the directory of the original shell).

function cdroot()
{
  while [[ $PWD != '/' && ${PWD##*/} != 'httpdocs' ]]; do cd ..; done
}

You can of course name the function whatever you like.

Some explanation: The first test ($PWD != '/') is a failsafe in case you do cdroot when you're not inside a httpdocs folder. It'll stop when you get to the root.

The second test (${PWD##*/} != 'httpdocs') is a bit more complicated. $PWD is a variable containing the path of the current directory. ${PWD##*/} trims everything up to and including the last slash.

share|improve this answer
    
The downside to this iterative one is that you lose your ability to just do a cd - afterwards to go back to where you were. –  Ezequiel Muns Jun 5 '13 at 23:45

I have a function called upto in my .bashrc which allows you to go up to any directory on the current path by name:

upto ()
{
    if [ -z "$1" ]; then
        return
    fi
    local upto=$1
    cd "${PWD/\/$upto\/*//$upto}"
}

I also have completion for this function, so that it gives me valid directory names and completion when I hit tab:

_upto()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local d=${PWD//\//\ }
    COMPREPLY=( $( compgen -W "$d" -- "$cur" ) )
}
complete -F _upto upto

In addition, I have another function jd which allows me to jump to any directory below the current one:

jd(){
    if [ -z "$1" ]; then
        echo "Usage: jd [directory]";
        return 1
    else
        cd **"/$1"
    fi
}

Example:

[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto h[TAB][TAB]
habitat       hippopotamus
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ upto hippopotamus
[/www/public_html/animals/hippopotamus] $ jd images
[/www/public_html/animals/hippopotamus/habitat/swamps/images] $ 
share|improve this answer
    
You could also add an alias for upto httpdocs. –  cjm Jun 3 '11 at 9:54
    
@drogbane: jd does not appear to work in every case, would you mind explaining how it works? –  Cesar Jan 19 '12 at 6:22
    
@Cesar it uses globstar (**). To enable this feature in your bash shell use shopt -s globstar. –  dogbane Jan 19 '12 at 8:37
    
These are awesome, thanks! –  Ibrahim Nov 14 '12 at 22:41
    
This is so brilliantly done, I wish I could upvote twice. –  droope Feb 2 '13 at 18:18

The simplest bash function that you can put into your .bashrc that I can think of (simple because it does not use loops or external processes) is:

cdup() {
    cd "${PWD/\/httpdocs\/*//httpdocs}"
}

This uses the Pattern substitution parameter expansion to replace everything after /httpdocs/ in $PWD with `/httpdocs'. It looks very messy because we have to escape the forward slashes in the path to differentiate them from the forward slashes in the bash expansion syntax. Plus do not escape forward slashes in the replacement string, so it also looks inconsistent.

If there is no /httpdocs/ in the current path then no substitutions will be perform and it will just change to the current directory.

For example, the substitution will replace /a/b/c/httpdocs/e/f/g with /a/b/c/httpdocs and cd into that directory.

The function needs to be in your current shell environment (either as a function or alias) since a child process cannot change the current directory of its parent. This is why I say to put it in your .bashrc and not in a shell script.

share|improve this answer
    
Incidentally, it's worth mentioning that this will take you as high up in the hierarchy as possible (which is probably the most useful use case anyway). –  Ibrahim Nov 14 '12 at 22:48

You could also put something like this in your profile:

alias cdh='cd $(echo $PWD | sed -e "s/\(.*\/httpdocs\)\/.*/\1/")'

The just typing cdh will get you to the topmost httpdocs directory in your current path.

share|improve this answer

It doesn't completely address your problem, but it will save on doing cd ../../../../../../ a bit. I've borrowed this from user unknown's post here.


up N

jump N directories up in the directory tree

Instead of typing

cd ../../../..

you just type

up 4

and a

cd -    

will bring you back

Put the function into your .bashrc to use it.

# (c) 2007 stefan w. GPLv3          
function up {
ups=""
for i in $(seq 1 $1)
do
        ups=$ups"../"
done
cd $ups
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.