-1

I have 2 folders set up:

/
  folder/
    subfolder/
      file.txt
  symlink-folder/
    subfolder/ -> /folder/subfolder

If I cd /symlink-folder/subfolder then run ls, I see file.txt, as I expect. However, if I then run mv file.txt .., I end up with this:

/
  folder/
    file.txt
    subfolder/
  symlink-folder/
    subfolder/ -> /folder/subfolder

Basically, the command moved file.txt to its parent directory, not the parent directory of the shell, as I would expect. If I run pwd, I see /symlink-folder/subfolder. If I run cd .., it navigates to /symlink-folder. Both of these work as I expect.

How do I set this up?

EDIT: a bit of testing, if I navigate into /symlink-folder/subfolder then run vi ../file and save, it creates a file in the original folder's parent as well, not the shell's parent. It appears that the symbolic link itself is behaving strangely, not the command that is using it. cd works, but any other command doesn't seem to.

ewok
  • 4,641

2 Answers2

2

Please read Why does ls .. show real parent content when I'm inside a symbolic link directory? and my answer there. And then this answer about cd and pwd.

A tool like your mv, your vim or ls (in the linked question) always knows its current working directory as a physical path. It could know the logical path if it examined the $PWD environment variable that should certainly be in the environment when the tool is invoked from a shell. Hardly any tool uses $PWD, the mentioned tools don't, we can say that not using $PWD is the common behavior.

Therefore for your mv .. means "the parent directory in the physical path to the current working directory".

After cd /symlink-folder/subfolder the logical path is /symlink-folder/subfolder, but the physical path is /folder/subfolder. For any tool that doesn't use $PWD .. will mean /folder. Only tools that do use $PWD will treat .. as /symlink-folder.

To make mv work as you want, you need to use $PWD one way or another. You can parse $PWD somehow and/or you can use a tool that uses the variable. The cd builtin in your shell and pwd (which may be a builtin or a separate executable) are such tools.

E.g. instead of mv file.txt .. you can do:

(cd -L .. && mv subfolder/file.txt .)

(where I used a subshell, so the current working directory of your main shell does not change). Here cd -L .. uses $PWD, but also your brain had to parse $PWD to know what string to prepend to file.txt. Such parsing can be automated, but it's quite cumbersome. If it's a one-time job then IMO using the brain for parsing is the right thing to do.

Alternatively you can do this:

mv file.txt "$(cd -L .. && pwd)"

Here cd -L .. uses $PWD and puts the subshell (executing the insisde of the command substitution) in .. according to the logical path. Then pwd prints the then-working directory (and I think ultimately it doesn't matter if it's pwd -L or pwd -P). This method does not require you to parse $PWD by hand (or rather by brain).

Another solution is to directly manipulate $PWD as a string:

mv file.txt "${PWD%/*}/"

${PWD%/*} expands to the content of $PWD without the last slash and everything after (Remove Smallest Suffix Pattern, here). This transforms /symlink-folder/subfolder into /symlink-folder. But if the current working directory was /, then the result would be an empty string which is wrong; therefore I postpend one / and in case of / I would get / (which is good because /.. means /). In our case of /symlink-folder/subfolder I get /symlink-folder/ which is as good as /symlink-folder when interpreted (by mv) as a destination directory.

This method should behave well for any $PWD. $PWD should always contain an absolute path whithout . or .. components (that could otherwise make the method misbehave).

0

You seem to describe a non-standard behavior. The man-page symlink(7) says: "The mv(1) and rm(1) commands do not follow symbolic links named as arguments, but respectively attempt to rename and delete them".

You might be able to workaround this problem by using two commands: cp the symlink and then rm the original one.

If the implementation of cp follows the man-pages, then the following arguments of cp may help:

-d     same as --no-dereference --preserve=links

-P, --no-dereference never follow symbolic links in SOURCE

harrymc
  • 498,455