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.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Does the command pwd in a shell script output the directory the shell script is in?

share|improve this question
    
@BinaryZebra: Yes, that is the full name of the command, but what does it return exactly? At the start of a script it is the pwd of the shell that is calling the script, not the directory that contains the script! – mkdrive2 Feb 12 at 3:16
    
No, I aready understand what you mean, but you seem to be mistakenly using the word "shell" and "shell script" synonymously. I think you meant "shell script" in your last comment. Correct me if I am wrong. – mkdrive2 Feb 12 at 4:12
    
Read my answer. May be of help. – BinaryZebra Feb 12 at 4:43
4  
Note that there is a difference between a program's output (what it prints to stdout and stderr) and its return value (on most systems, effectively an eight-bit unsigned integer derived from what the program's main function returned, or what it passed to exit()). pwd prints its working directory (if possible); it returns zero if it succeeded and nonzero if it failed. – Blacklight Shining Feb 12 at 9:33
1  
Welcome to Unix & Linux StackExchange. You appear to have asked a question with a Yes/No answer, leading others to guess what you really want to know. A better question for this site might have been "What does pwd return when called from inside a shell script?" or "When a shell script is running, how can it find the directory containing the script?" – joeytwiddle Feb 12 at 19:04
up vote 17 down vote accepted

There are three independent "directories" at play here:

  1. your current shell's current working directory,
  2. the shell script's current working directory, and
  3. the directory containing the shell script.

To demonstrate that they are independent, you can write a shell script, saved to /tmp/pwd.sh, containing:

#!/bin/sh
pwd
cd /var 
pwd

You can then change your pwd (#1 above) to /:

cd /

and execute the script:

/tmp/pwd.sh

which starts off by demonstrating your existing pwd (#1), then changes it to /var and shows it again (#2). Neither of those pwd's were "/tmp", the directory that contains /tmp/pwd.sh (#3).

share|improve this answer
    
It will not necessarily display the directory that contains the shell script, if that's causing confusion. – Jeff Schaller Feb 12 at 2:41
2  
Oh, right. The shell script can change pwd. I did not know that. But your answer is formulated a little confusingly. I would rewrite it... – mkdrive2 Feb 12 at 2:55
    
Does that edit help? – Jeff Schaller Feb 12 at 2:57
1  
rewrote it to try another way ... – Jeff Schaller Feb 12 at 3:06
3  
It's worth noting that programs (including scripts; scripts are programs) inherit their working directories from their parents. A process can change its own working directory, but that won't affect its parent's. cd and commands like it work because they are builtins that run within the shell, rather than external programs in their own right. – Blacklight Shining Feb 12 at 9:39

Present (or Current) Working Directory

Does the command pwd in a shell script return the directory the shell script is in?

No.

Firstly, by definition, no shell script or shell command returns anything other than a numeric exit status between 0 - 255. That's axiomatic, but not generally not what people mean when they ask these types of questions.

Secondly, pwd is both a Bourne shell builtin and a standard system binary. Either one prints the logical or physical current working directory, which is generally:

  1. Your location in the directory structure when you call a script or binary.
  2. Your current location after changing the working directory with cd or other utilities and builtins that modify the current working directory such as pushd or popd.

If you want the directory of the current script, use the dirname utility as described in the final section below.

Quick Test of pwd

As a quick test to see what pwd really prints, you can run the following:

# Create a shell script containing pwd.
cat <<-EOF > /tmp/test_pwd.sh
#!/bin/sh

pwd
EOF

# Make the script executable.
chmod 755 /tmp/test_pwd.sh

# Go somewhere on the filesystem, and call the test script.
cd /etc
/tmp/test_pwd.sh

This will print /etc, not /tmp, because your current working directory is currently /etc. This is the expected behavior.

Getting the Directory Containing a Script

You're probably asking this question because you want to find the directory of the current script. In the general case, the following is the quick-and-dirty solution:

#!/usr/bin/env bash
echo $(dirname "$0")

This works because $0 generally contains the pathname used to invoke the script being executed, and the shell expansion uses the dirname utility to return the path excluding the filename portion. You can do something similar, but less portably, with the Bash parameter expansion "${0%/*}".

This is all a vast over-simplification, of course. Please read the Bash manual (especially the sections on positional parameters, special parameters, and BASH_SOURCE) and the man pages for readlink and realpath to get a fuller understanding of what the edge cases are, of which there are several.

However, in day-to-day scripting, the directory component of $0 is sufficient to tell you what you want to know. If you are doing something complicated enough where $0 doesn't hold the information you actually need, and you require more complicated constructs like:

echo $(dirname "$(realpath "$0")")

then you're probably making your life more difficult than it needs to be.

share|improve this answer
1  
This is a good answer, but you're describing what pwd prints, not what it returns. IMO, the difference is worth noting. – Blacklight Shining Feb 12 at 9:40
1  
@BlacklightShining By definition, no shell script or shell command returns anything other than a numeric exit status between 0 - 255. That's axiomatic, but not generally not what people mean when they ask these types of questions. YMMV. – CodeGnome Feb 12 at 15:15

pwd returns 0 unless its current working directory cannot be opened.

mkdir /tmp/d; cd "$_"
pwd && pwd -P; echo "$?"
rmdir ../d
pwd && pwd -P; echo "$?"

/tmp/d
/tmp/d
0
/tmp/d
pwd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
1
share|improve this answer
4  
pwd prints a directory to the command line. I believe that that is what the OP is asking about, not the exit code. – BinaryZebra Feb 12 at 6:46

There is this concept called cwd that every running process keeps track of.

Or better worded: the kernel keeps an idea of the cwd of each process.

That could be read with (for a system with /proc):

readlink /proc/$PID_of_PROCESS/cwd

And for the running shell (of which its PID should be $$):

$ readlink /proc/$$/cwd

The shell keeps track of the same information (even if sometimes they might get out of sync) in the variable $PWD, and in the command pwd:

$ cd /tmp; echo "Present working directory: $PWD"
Present working directory: /tmp
$ cd /tmp; echo "Current working directory: $(pwd)"
Current working directory: /tmp

So, the pwd command presents the cwd of each process:

The place each process stands inside the directory tree.

Each time a shell, script or process execute a cd, all those variables get updated (except some corner cases).

A shell could change its pwd by executing a cd /tmp for example.

An script could tell the shell under which it is running to change the pwd with a cd /tmp as well.

Or some other c process might call the kernel to execute an equivalent of a cd /tmp.

In all cases, the kernel cwd and (if the process is a shell) the shell's pwd gets updated.

share|improve this answer

It returns directory from where it is called/run from & not where the script is !

Here is try.sh :

echo "The current working directory: $PWD"

This output will make more clear :

[akarpe@ADM-PROD-OMNI ~]$ sh try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ sh try/try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ sh ./try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ sh ./try/try.sh
The current working directory: /mnt/home/akarpe
[akarpe@ADM-PROD-OMNI ~]$ cd try
[akarpe@ADM-PROD-OMNI try]$ sh ./try.sh
The current working directory: /mnt/home/akarpe/try
[akarpe@ADM-PROD-OMNI try]$ sh ../try.sh
The current working directory: /mnt/home/akarpe/try
share|improve this answer
    
If the answer was yes the second output would refer to /mnt/home/akarpe/try. It is not a good idea to try to prove this by calling a shell script from the directory that contains the script. That fucks with the mind. :) – mkdrive2 Feb 12 at 3:06
    
This output will make more clear : [akarpe@ADM-PROD-OMNI ~]$ sh try.sh The current working directory: /mnt/home/akarpe [akarpe@ADM-PROD-OMNI ~]$ sh try/try.sh The current working directory: /mnt/home/akarpe [akarpe@ADM-PROD-OMNI ~]$ sh ./try.sh The current working directory: /mnt/home/akarpe [akarpe@ADM-PROD-OMNI ~]$ sh ./try/try.sh The current working directory: /mnt/home/akarpe – Ashish Karpe Feb 12 at 4:39
    
[akarpe@ADM-PROD-OMNI ~]$ cd try [akarpe@ADM-PROD-OMNI try]$ sh ./try.sh The current working directory: /mnt/home/akarpe/try [akarpe@ADM-PROD-OMNI try]$ sh ../try.sh The current working directory: /mnt/home/akarpe/try – Ashish Karpe Feb 12 at 4:39
    
@mkdrive2 Let me update my answer ! Thanks – Ashish Karpe Feb 12 at 4:40

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.