Why can't I work with files in ".." from a symbolic link?

I have the following directory structure:

misha@misha-lmd:~/tmp$ ls -l
total 4.0K
-rw-r--r-- 1 misha lmd 21 Feb 18 21:00 hello.py
lrwxrwxrwx 1 misha lmd 20 Feb 18 21:01 symlink -> /home/misha/nobackup/

      

Next, I'll try the following:

misha@misha-lmd:~/tmp$ cd symlink
misha@misha-lmd:~/tmp/symlink$ cat ../hello.py 
cat: ../hello.py: No such file or directory

      

Why doesn't it work?

If I do this instead:

misha@misha-lmd:~/tmp/symlink$ cd ..
misha@misha-lmd:~/tmp$ cat hello.py
print "Hello World!"

      

Then everything is fine. cd handles .. correctly, but cat doesn't. What is this witchcraft, and how can I make everything work the way I want?

EDIT

Ok, thanks to some of the answers here, I found out a little more about what's going on. First, it cd

's not actually executable, it's a shell builtin (in this case bash):

misha@misha-lmd:~/tmp$ type cd
cd is a shell builtin

      

If you are man bash

, you can find everything about the environment variables that bash uses for its household, including moving directories. There are other built-in modules, such as pwd

those that have counterparts that are actually executables:

misha@misha-lmd:~/tmp/symlink$ type pwd
pwd is a shell builtin
misha@misha-lmd:~/tmp/symlink$ /bin/pwd
/home/misha/nobackup
misha@misha-lmd:~/tmp/symlink$ /bin/pwd -L
/home/misha/tmp/symlink

      

The executable /bin/pwd

prints the default physical path, but it can also print the logical path specified by the `-L 'switch. Similarly, when I try to do:

misha@misha-lmd:~/tmp/symlink$ cat ../hello.py 
cat: ../hello.py: No such file or directory

      

an error occurs because it is ..

interpreted as a physical parent directory and not a logical one. This allows me to clarify my question as:

When I specify a command line argument for an executable, how can I get ..

to refer to the logical parent and not the physical?

+3


source to share


3 answers


Because the directory ..

in your symbolic directory is your home directory.

../something

means "change to directory ..

", not "strip the last component of the path".



You can try pwd -P

to find out where you are after you changed the symbolic link.

+4


source


It doesn't work because it doesn't /home/misha/hello.py

. A symbolic link does not create a new directory, but points to a linked one. So when you connect to a symbolic link, you are actually connecting to that directory,



Did you expect the shell to remember where you came from from the symlink? Well, it doesn't work like that :)

+1


source


Try

cat $(cd ..; pwd)/hello.pycat

      

Don't know if this helps you.

EDIT:
If you really need it , here's a way to do it (but it's kind of ugly):

$ lcat ( ) ( cd "${1%/*}"; cat "${1##*/}"; )
# use it like 'cat'
$ lcat ../hello.py

      

Using a function ( ... )

instead of a { ... }

body makes it cd

a subclass instead of the current wrapper.
When I try, it works with "filename completion" too.
But this solution is only cat

, it might be more difficult to use for other commands as I think.

$ lcmd ( ) ( local cmd="$1"; shift; cd "${1%/*}"; $cmd "${1##*/}"; )

      

Then, for example, lcmd cat ../hello.py

0


source







All Articles