Why do you need ./ (dot-slash) before executable or script name to run it in bash?

前端 未结 9 930
耶瑟儿~
耶瑟儿~ 2020-11-22 03:59

When running scripts in bash, I have to write ./ in the beginning:

$ ./manage.py syncdb

If I don\'t, I get an error message:

相关标签:
9条回答
  • 2020-11-22 04:31

    Rationale for the / POSIX PATH rule

    The rule was mentioned at: Why do you need ./ (dot-slash) before executable or script name to run it in bash? but I would like to explain why I think that is a good design in more detail.

    First, an explicit full version of the rule is:

    • if the path contains / (e.g. ./someprog, /bin/someprog, ./bin/someprog): CWD is used and PATH isn't
    • if the path does not contain / (e.g. someprog): PATH is used and CWD isn't

    Now, suppose that running:

    someprog
    

    would search:

    • relative to CWD first
    • relative to PATH after

    Then, if you wanted to run /bin/someprog from your distro, and you did:

    someprog
    

    it would sometimes work, but others it would fail, because you might be in a directory that contains another unrelated someprog program.

    Therefore, you would soon learn that this is not reliable, and you would end up always using absolute paths when you want to use PATH, therefore defeating the purpose of PATH.

    This is also why having relative paths in your PATH is a really bad idea. I'm looking at you, node_modules/bin.

    Conversely, suppose that running:

    ./someprog
    

    Would search:

    • relative to PATH first
    • relative to CWD after

    Then, if you just downloaded a script someprog from a git repository and wanted to run it from CWD, you would never be sure that this is the actual program that would run, because maybe your distro has a:

    /bin/someprog
    

    which is in you PATH from some package you installed after drinking too much after Christmas last year.

    Therefore, once again, you would be forced to always run local scripts relative to CWD with full paths to know what you are running:

    "$(pwd)/someprog"
    

    which would be extremely annoying as well.

    Another rule that you might be tempted to come up with would be:

    relative paths use only PATH, absolute paths only CWD

    but once again this forces users to always use absolute paths for non-PATH scripts with "$(pwd)/someprog".

    The / path search rule offers a simple to remember solution to the about problem:

    • slash: don't use PATH
    • no slash: only use PATH

    which makes it super easy to always know what you are running, by relying on the fact that files in the current directory can be expressed either as ./somefile or somefile, and so it gives special meaning to one of them.

    Sometimes, is slightly annoying that you cannot search for some/prog relative to PATH, but I don't see a saner solution to this.

    0 讨论(0)
  • 2020-11-22 04:36

    When the script is not in the Path its required to do so. For more info read http://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_01.html

    0 讨论(0)
  • 2020-11-22 04:37

    Because on Unix, usually, the current directory is not in $PATH.

    When you type a command the shell looks up a list of directories, as specified by the PATH variable. The current directory is not in that list.

    The reason for not having the current directory on that list is security.

    Let's say you're root and go into another user's directory and type sl instead of ls. If the current directory is in PATH, the shell will try to execute the sl program in that directory (since there is no other sl program). That sl program might be malicious.

    It works with ./ because POSIX specifies that a command name that contain a / will be used as a filename directly, suppressing a search in $PATH. You could have used full path for the exact same effect, but ./ is shorter and easier to write.

    EDIT

    That sl part was just an example. The directories in PATH are searched sequentially and when a match is made that program is executed. So, depending on how PATH looks, typing a normal command may or may not be enough to run the program in the current directory.

    0 讨论(0)
  • 2020-11-22 04:37

    When bash interprets the command line, it looks for commands in locations described in the environment variable $PATH. To see it type:

    echo $PATH
    

    You will have some paths separated by colons. As you will see the current path . is usually not in $PATH. So Bash cannot find your command if it is in the current directory. You can change it by having:

    PATH=$PATH:.
    

    This line adds the current directory in $PATH so you can do:

    manage.py syncdb
    

    It is not recommended as it has security issue, plus you can have weird behaviours, as . varies upon the directory you are in :)

    Avoid:

    PATH=.:$PATH
    

    As you can “mask” some standard command and open the door to security breach :)

    Just my two cents.

    0 讨论(0)
  • 2020-11-22 04:40

    When you include the '.' you are essentially giving the "full path" to the executable bash script, so your shell does not need to check your PATH variable. Without the '.' your shell will look in your PATH variable (which you can see by running echo $PATH to see if the command you typed lives in any of the folders on your PATH. If it doesn't (as is the case with manage.py) it says it can't find the file. It is considered bad practice to include the current directory on your PATH, which is explained reasonably well here: http://www.faqs.org/faqs/unix-faq/faq/part2/section-13.html

    0 讨论(0)
  • 2020-11-22 04:47

    All has great answer on the question, and yes this is only applicable when running it on the current directory not unless you include the absolute path. See my samples below.

    Also, the (dot-slash) made sense to me when I've the command on the child folder tmp2 (/tmp/tmp2) and it uses (double dot-slash).

    SAMPLE:

    [fifiip-172-31-17-12 tmp]$ ./StackO.sh
    
    Hello Stack Overflow
    
    [fifi@ip-172-31-17-12 tmp]$ /tmp/StackO.sh
    
    Hello Stack Overflow
    
    [fifi@ip-172-31-17-12 tmp]$ mkdir tmp2
    
    [fifi@ip-172-31-17-12 tmp]$ cd tmp2/
    
    [fifi@ip-172-31-17-12 tmp2]$ ../StackO.sh
    
    Hello Stack Overflow
    
    0 讨论(0)
提交回复
热议问题