Find a Process's Working Directory with pwdx

Run pwdx when a running process is writing files somewhere unexpected and you need its actual current directory, not the one you assume it started in. It takes one or more PIDs and prints the working directory each one is using right now. The examples below use pwdx from procps-ng 4.0.4, shipped here as Ubuntu package procps version 2:4.0.4-4ubuntu3.3.

Allow about ten minutes. You need a shell and a process ID you are allowed to inspect. Everything here is read-only: pwdx never changes a process's directory, stops it or restarts a service. Reach for elevated privileges only if your system policy demands them for the target process.

1. Check what is actually installed

Confirm the binary and version before you trust anything it tells you:

$ command -v pwdx
/usr/bin/pwdx
$ pwdx --version
pwdx from procps-ng 4.0.4
$ dpkg-query -W -f='${Package} ${Version}\n' procps
procps 2:4.0.4-4ubuntu3.3

Checkpoint: if command -v pwdx finds nothing, install the distribution's procps package the normal way. Do not drop a replacement binary into a system directory just to get this guide working.

2. Point it at your own shell

The shell expands $$ to its own PID, which makes a safe first target:

$ pwdx $$
1937214: /home/alice/src/manpages/prompts/generated/pwdx-1

Your PID and path will differ. The output is always PID, colon, working directory. Compare it against the shell's own idea of where it is:

$ pwd
/home/alice/src/manpages/prompts/generated/pwdx-1

Do not keep that example PID around as if it means something later. PIDs get recycled the moment a process exits, so capture one when you need it and use it straight away.

3. Test on a throwaway process instead of a real service

Start a disposable sleep job rather than poking a service you care about. The only state this touches is the one process, and the final kill line cleans it up:

$ sleep 60 &
[1] 1938000
$ pid=$!
$ pwdx "$pid"
1938000: /home/alice/src/manpages/prompts/generated/pwdx-1
$ kill "$pid"
$ wait "$pid" 2>/dev/null || true

Job number and PID will vary. A working result shows the directory sleep inherited, and none of this needs sudo when you own the process. If you bail out before the cleanup line, run kill "$pid" while that shell variable still exists, or hunt down the leftover process before you close the shell.

Checkpoint: chasing a real service instead? Use its actual PID rather than spinning up a second copy. Find it with your process supervisor's status command or ps, then run pwdx PID. Starting a duplicate service risks a port conflict and a misleading answer.

4. Check several PIDs in one go

List more than one PID and each gets its own line:

$ pwdx $$ 1938000
1937214: /home/alice/src/manpages/prompts/generated/pwdx-1
1938000: /home/alice/src/manpages/prompts/generated/pwdx-1

Handy for comparing a parent and child, or a batch of workers launched from the same place. The order here follows the order you typed the PIDs, but a script should parse the PID and directory rather than lean on display order beyond the documented format.

Quote a PID variable as shown above. PIDs are numeric, but quoting stops an empty or unexpected value from expanding into something the shell misreads. Validate anything that came from outside your script before it reaches a command line.

5. Read the errors, they are telling you something real

A process can exit between the moment you grab its PID and the moment pwdx reads it. Reproduce that with a PID that cannot exist:

$ pwdx 999999999
999999999: No such process
$ printf 'exit status: %s\n' "$?"
exit status: 1

Exact wording comes from the installed procps-ng build. A non-zero exit means the lookup failed, full stop. Get a fresh PID from the process list rather than assuming an old one still points at the same program.

Permission denied means something different: the process exists but your account cannot read what the lookup needs. Confirm the PID and your account first, then, if policy allows it:

$ sudo pwdx PID

Replace PID with a current numeric process ID. A successful sudo lookup does not by itself prove the process is the service you think it is, so confirm the command separately with a proper read-only process listing. If the process has already exited, no amount of privilege brings back its old working directory.

6. Keep the result in context

A working directory is process state, not the directory holding the executable and not a service's configured data directory. A daemon can change directory after startup, inherit one from its supervisor, or end up pointing at a path that no longer exists on disk. Treat the answer as a snapshot, not a permanent fact.

For automation, check the exit status and keep the raw output instead of assuming a path exists:

$ if output=$(pwdx "$pid"); then
>     printf '%s\n' "$output"
> else
>     printf 'pwdx could not inspect PID %s\n' "$pid" >&2
>     exit 1
> fi

This assumes pid was set to a current PID earlier in the same shell. It never turns a failed lookup into an empty or falsely valid path. Never feed command output straight into a destructive command without checking both the value and the target it names.

Done means