Question

I have a shell and I use pwd to show in which directory I am. but when I'm in directory that it's a symlink it show the physical directory not the symlink

import subprocess as sub

def execv(command, path):
    p = sub.Popen(['/bin/bash', '-c', command],
                    stdout=sub.PIPE, stderr=sub.STDOUT, cwd=path)
    return p.stdout.read()[:-1]

If I have folder /home/foo/mime that it's symlink to /usr/share/mime when I call

execv('pwd', '/home/foo/mime')

I got /usr/share/mime

My code for shell look like this:

    m = re.match(" *cd (.*)", form['command'])
    if m:
        path = m.group(1)
        if path[0] != '/':
            path = "%s/%s" % (form['path'], path)
        if os.path.exists(path):
            stdout.write(execv("pwd", path))
        else:
            stdout.write("false")
    else:
        try:
            stdout.write(execv(form['command'], form['path']))
        except OSError, e:
            stdout.write(e.args[1])

And I have client in JavaScript

(probably returning result of the command and new path as JSON will be better).

Is there a way to make pwd return path to the symlink instead of the physical directory.

Was it helpful?

Solution

Only the current shell knows it is using a symbolic link to access the current directory. This information is normally not passed to children processes so they only know the current directory by its real path.

Should you want this information to be known to sub-processes, you need to define a way to pass it, for example through an argument or an environment variable. Exporting PWD from the shell might just work.

OTHER TIPS

If you want to resolve symlink, you probably want to use pwd -P, below is example from ZSH and BASH (behavior is same).

ls -l /home/tom/music
lrwxr-xr-x  1 tom  tom  14  3 říj  2011 /home/tom/music -> /mnt/ftp/music

cd /home/tom/music

tom@hal3000 ~/music % pwd
/home/tom/music
tom@hal3000 ~/music % pwd -P
/mnt/ftp/music

Using FreeBSD's /bin/pwd i get this though:

tom@hal3000 ~/music % /bin/pwd 
/mnt/ftp/music
tom@hal3000 ~/music % /bin/pwd -P
/mnt/ftp/music
tom@hal3000 ~/music % /bin/pwd -L
/home/tom/music

So maybe your pwd(1) supports the -L too if you want the symlink unresolved, since this version assumes -P by default ?

Use shell=True in Popen:

import os
from subprocess import Popen, PIPE

def shell_command(command, path, stdout = PIPE, stderr = PIPE):
  proc = Popen(command, stdout = stdout, stderr = stderr, shell = True, cwd = path)
  return proc.communicate() # returns (stdout output, stderr output)

print "Shell pwd:", shell_command("pwd", "/home/foo/mime")[0]

os.chdir("/home/foo/mime")
print "Python os.cwd:", os.getcwd()

This outputs:

Shell pwd: /home/foo/mime
Python os.cwd: /usr/share/mime

AFAIK, there's no way to get the shell pwd in python, other than actually asking the shell itself like above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top