Skip to main content

Why doesn"t "cd' work in a bash shell script?


I'm trying to write a small script to change the current directory to my project directory:




#!/bin/bash
cd /home/tree/projects/java



I saved this file as proj, changed the chmod, copied it to /usr/bin . When I call it by: proj , it does nothing. What am I doing wrong?


Source: Tips4allCCNA FINAL EXAM

Comments

  1. Shell scripts are run inside a subshell, and each subshell has its own concept of what the current directory is. The cd succeeds, but as soon as the subshell exits, the previous current directory is restored.

    One way to get around this is to use an alias instead:

    alias proj="cd /home/tree/projects/java"

    ReplyDelete
  2. Nothing. You've changed the directory, but only within the subshell that runs the script.

    You can run the script in your current process with the "dot" command:

    . proj


    But I'd prefer Greg's suggestion to use an alias in this simple case.

    ReplyDelete
  3. Jeremy Ruten's idea of using a symlink triggered a thought that hasn't crossed any other answer. Use:

    CDPATH=:$HOME/projects


    The leading colon is important; it means that if there is a directory 'dir' in the current directory, then 'cd dir' will change to that, rather than hopping off somewhere else. With the value set as shown, you can do:

    cd java


    and, if there is no sub-directory called java in the current directory, then it will take you directly to $HOME/projects/java - no aliases, no scripts, no dubious execs or dot commands.

    My $HOME is /Users/jleffler; my $CDPATH is:

    :/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work

    ReplyDelete
  4. The cd is done within the scripts' shell, the shell exits, and then you are left in the directory you were... source the script, don't run it. instead of:

    # ./myscript.sh


    do

    # . ./myscript.sh


    (notice the dot, space, and script name)

    ReplyDelete
  5. The cd in your script technically worked as it changed the directory of the shell that ran the script, but that was a separate process forked from your interactive shell.

    A Posix-compatible way to solve this problem is to define a shell procedure rather than a shell-invoked command script.

    jhome () {
    cd /home/tree/projects/java
    }


    You can just type this in or put it in one of the various shell startup files.

    ReplyDelete
  6. To make a bash script that will cd to a select directory :

    Create the script file


    #!/bin/sh
    # file : /scripts/cdjava
    #
    cd /home/askgelal/projects/java


    Then create an alias in your startup file.


    #!/bin/sh
    # file /scripts/mastercode.sh
    #
    alias cdjava='. /scripts/cdjava'





    I created a startup file where I dump all my aliases and custom functions.
    Then I source this file into my .bashrc to have it set on each boot.



    For example, create a master aliases/functions file: /scripts/mastercode.sh
    (Put the alias in this file.)


    Then at the end of your .bashrc file:


    source /scripts/mastercode.sh






    Now its easy to cd to your java directory, just type cdjava and you are there.

    ReplyDelete
  7. When you fire a shell script, it runs a new instance of that shell (/bin/bash). Thus, your script just fires up a shell, changes the directory and exits. Put another way, cd (and other such commands) within a shell script do not affect nor have access to the shell from which they were launched.

    ReplyDelete
  8. It only changes the directory for the script itself, while your current directory stays the same.

    You might want to use a symbolic link instead. It allows you to make a "shortcut" to a file or directory, so you'd only have to type something like cd my-project.

    ReplyDelete
  9. to navigate directories quicky, there's $CDPATH, cdargs, and ways to generate aliases automatically

    http://jackndempsey.blogspot.com/2008/07/cdargs.html

    http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html

    http://articles.techrepublic.com.com/5100-10878_11-5827311.html

    ReplyDelete
  10. You can combine an alias and a script:

    alias proj='cd \`/usr/bin/proj !*\`"


    provided that the script echos the destination path. Note that those are backticks surrounding the script name.

    For example, your script could be

    #!/bin/bash
    echo /home/askgelal/projects/java/$1


    The advantage with this technique is that the script could take any number of command line parameters and emit different destinations calculated by possibly complex logic.

    ReplyDelete
  11. You can do following:

    #!/bin/bash
    cd /your/project/directory
    # start another shell and replacing the current
    exec /bin/bash


    EDIT: This could be 'dotted' as well, to prevent creation of subsequent shells.

    Example:

    . ./previous_script (with or without the first line)

    ReplyDelete
  12. LOOOOOng time after, but I did the following:

    create a file called case

    paste the following in the file:

    #!/bin/sh

    cd /home/"$1"


    save it and then:

    chmod +x case


    I also created an alias in my .bashrc:

    alias disk='cd /home/; . case'


    now when I type:

    case 12345


    essentially I am typing:

    cd /home/12345


    You can type any folder after 'case':

    case 12

    case 15

    case 17


    which is like typing:

    cd /home/12

    cd /home/15

    cd /home/17


    respectively

    In my case the path is much longer - these guys summed it up with the ~ info earlier.

    ReplyDelete
  13. You can combine Adam & Greg's alias and dot approaches to make something that can be more dynamic—

    alias project=". project"


    Now running the project alias will execute the project script in the current shell as opposed to the subshell.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex