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.

Linux has a /proc directory and file‑system, which as far as I can tell, is not part of POSIX. In each /proc/$PID subdirectories, is a symbolic link, cwd, pointing to the actual working directory of the process of this PID (the cwd link is always up to date).

This symbolic link is convenient for some use case, like working with distinct shells and exchanging files between the two shells (formally, their working directories).

Is there a simple way to get something similar, only using POSIX feature?

More on the question

After a comment, more precision: it does not have to necessarily be a link and an environment variable lile $<PID>_CWD, would be as much fine too, although at first sigh, I don't believe such a solution exist. It just has to be easy to refer to (ex. symbolic link or environment variable) and be always up to date each time the other process switch it's working directory.

The solution does not need to necessarily be POSIX, and the most important aspect is portability, but POSIX is surely a guarantee.

share|improve this question
1  
Are you wanting POSIX, or portable? Things can be portable without being defined in POSIX. –  Patrick Jul 8 at 13:50
1  
I don't think POSIX would concern itself with this fine of a detail and narrow of a use case. Solaris and AIX both have a pwdx command, so you may just create an alias or function called pwdx on Linux that wraps around readlink if you're looking for something portable. –  Joel Davis Jul 8 at 14:07
1  
Actually, on my RHEL5 system there is a pwdx command that comes with procps so that may be your answer. –  Joel Davis Jul 8 at 14:10
1  
@JoelDavis Actually, almost every Linux and Solaris has pwdx. But FreeBSD doesn't. –  enedil Jul 8 at 14:18
2  
Fun fact: getcwd(3) used to work by calling stat(".") and readdir(".."), finding a matching inode number, and repeating the process upward until it hit the root directory. Good luck doing that in the context of another process. (I suppose one could use ptrace to inject a call to getcwd...) –  Zack Jul 8 at 20:22
show 4 more comments

3 Answers 3

I have a solution that uses lsof. It is not installed on BSD by default so if anyone want to use it on BSD, it is required to install it.

Make a shell script:

#!/bin/sh
lsof -p $1 | grep cwd | awk '{print $9}'

Copy it to a directory in your path. It prints the working directory of PID given in the first argument, I.E.

$ script 1987
/home/enedil
share|improve this answer
2  
By the way, this little variation too: lsof -p $PID | awk '/cwd/{print $9}'. –  Hibou57 Jul 8 at 15:38
    
@Hibou57 ok, I'm not an AWK expert. –  enedil Jul 8 at 15:39
1  
+1, I did not want you to stay on 888 :p –  Ramesh Jul 8 at 16:24
1  
You can save a little on lsof overhead with just lsof -d cwd -a -p $1 –  mr.spuratic Jul 8 at 17:25
add comment

POSIX doesn't offer much in terms of getting information about unrelated processes. There's only ps, really, and it doesn't give any information about the current directory. The C-level APIs aren't any better (in fact most of the information retrieved by ps can only be retrieved by parsing its output¹).

Funnily enough POSIX does offer a portable way to go the other way round: given a file, you can find out which processes have it open by calling fuser. The following snippet lists the PIDs of the processes that have a particular working directory:

fuser -f "$directory_name" 2>&1 | sed -e '$!d' -e 's/.*://' -e 's/  */\
/' | sed -n 's/c$//p'

If you want information about processes in a way that's portable in practice, use lsof. The author of lsof has done the work of implementing all the different ways of retrieving information on different unix variants.

For casual browsing:

lsof -a -p "$pid" -d cwd

For automated parsing:

lsof -a -p "$pid" -d cwd -F n | sed -e '1d' -e '2s/^n//'

Note that lsof replaces newlines by the string \n.

Some Unix variants offer methods that don't require third-party software, but these methods will be perforce specific to each variant. On a very related note, see Portability of file descriptor links

¹ Some old unices has ps setuid root and reading kernel memory, so using that setuid binary was the only way to obtain this information.

share|improve this answer
add comment

I will contribute my own answer.

An option, in the context of interactive shell (the question focuses on this context), could be automatically maintaining a link à la /proc/$PID/cwd, using the automation opportunity Bash provides:

PROMPT_COMMAND="ln -sfT \$(pwd) ~/$LINK_NAME"

The f option is required, as the link will be frequently overridden. The T option is required, as otherwise it seems the f option does work properly.

Shells may be made cooperative, using this in ex., ~/.bashrc:

if [ -v CWD_LINK_NAME ]; then
   PROMPT_COMMAND='ln -sfT "$(pwd)" "'$CWD_LINK_NAME'";'$PROMPT_COMMAND
   declare -r CWD_LINK_NAME
   function rm_cwd_link() {
      rm "$CWD_LINK_NAME"
   }
   trap rm_cwd_link EXIT
fi

A shell or a terminal may be executed with CWD_LINK_NAME set to any relevant value. Ex. CWD_LINK_NAME="~/$SOME_ROLE_NAME" gnome-terminal

Another alternative, is using the same concept to track the pear working directory in a variable, this tracking being based on both @Gilles and @enedil contributions:

PROMPT_COMMAND="PEAR_WD=\$(lsof -p $PID | awk '/cwd/{print \$9}')"

However, this is less accurate and less handy, while it may still be the only way for the rare cases the $PROMPT_COMMAND cannot be set in the other shell.

I'm in favour of the first option (still waiting before selecting an answer, if ever there are other contributions to come).

share|improve this answer
add comment

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.