Behavior of Cd/Bash on Symbolic Links

Behavior of cd/bash on symbolic links

According to help cd,

  Options:
-L force symbolic links to be followed: resolve symbolic
links in DIR after processing instances of `..'
-P use the physical directory structure without following
symbolic links: resolve symbolic links in DIR before
processing instances of `..'

In other words, -L means using the logical structure, whereas -P uses the actually physical directory structure.

The logical structure is like this,

$ tree a
a
└── b
└── symlink -> ..

The actual physical structure when you go to a/b/symlink is,

a

If you want to use the real .., then you must also use cd -P:

          The -P option says to use the physical directory
structure instead of following symbolic links (see
also the -P option to the set builtin command);
the -L option forces symbolic links to be followed.

An example,

$ cd
$ cd a/b/symlink # physical location is at a/
$ cd .. # now is at a/b
$ cd symlink # goes back to a/b/symlink
$ cd -P .. # follow physical path (resolve all symlinks)
$ pwd -P # -P is optional here to show effect of cd ..
/home/sarnold
$

Why does `cd ..` reflect symlink traversal, whereas `ls ..`does not?

A directory doesn't know what symbolic link you used to get to it; .. is an actual directory entry that points to the real parent directory. But when you use the shell command cd .., bash cheats. It knows what path you used to get there (it's in $PWD), so it just removes the last component of that and changes to the resulting directory.

You can use the same trick yourself for the benefit of other commands by using "${PWD%/*}" instead of ..:

ls "${PWD%/*}"

If I want my symbolic link to become active on a main (or dev) view, do I need to check it in?


Do I need to check-in a newly created file symlink for the link to become active globally?

No: the step 5 refers to the parent folder of the element you are creating (here a symlink).

For that element (created in step 3), you would need to check in the parent folder in order for that folder to list it as its sub-elements.

As long as the parent folder is not checked in, your new element remains visible only in your view.

perl compilation: 'Too many levels of symbolic links'

Thank you for the pointer @choroba.

Following was the root cause.

In <perl-5.28.3>/t/op/exec.t file, we find the following around line 114:

$rc = system { "lskdfj" } "lskdfj";
unless( ok($rc == 255 << 8 or $rc == -1 or $rc == 256 or $rc == 512) ) {
print "# \$rc == $rc\n";
}

unless ( ok( $! == 2 or $! =~ /\bno\b.*\bfile/i or
$! == 13 or $! =~ /permission denied/i or
$! == 22 or $! =~ /invalid argument/i ) ) {
diag sprintf "\$! eq %d, '%s'\n", $!, $!;
}

In my environment PATH env variable value was

[user@hostname perl-5.28.3]$ echo $PATH
/bin:/usr/lib64/qt-3.3/bin:/bin:/usr/bin:/usr/dev_infra/platform/bin:/usr/dev_infra/generic/bin:/usr/local/bin:/usr/local/ade/bin

Within this PATH, for following paths ls attempt is throwing error 'Too many levels of symbolic links'

[user@hostname perl-5.28.3]$ ls -i  /usr/local/bin /usr/local/ade/bin
ls: cannot access /usr/local/bin: Too many levels of symbolic links
ls: cannot access /usr/local/ade/bin: Too many levels of symbolic links

[user@hostname perl-5.28.3]$ ls -ltr /usr/local
lrwxrwxrwx. 1 root root 20 Mar 30 2017 bin -> ./packages/local/bin
lrwxrwxrwx. 1 root root 18 Mar 30 2017 ade -> /usr/local/nde/ade

After removing offending paths from PATH, make test is running successfully

[user@hostname perl-5.28.3]$  export PATH=/bin:/usr/lib64/qt-3.3/bin:/bin:/usr/bin:/usr/dev_infra/platform/bin:/usr/dev_infra/generic/bin

[user@hostname perl-5.28.3]$ make test

All tests successful.
Elapsed: 1611 sec
u=14.47 s=44.63 cu=731.82 cs=575.84 scripts=2474 tests=1209537

How to follow a symbolic/soft link in cmd or PowerShell?

For your question i made this batch file:

mkdir truedir
dir > truedir\fileone.txt
mklink /d symdir truedir
cd symdir
dir

And i have found no problem to get the content of the symblic link to a directory from command prompt.
No problem also with powershell 5.1 (win 10):

Get-ChildItem C:\Users\<user>\OneDrive\Desktop\test2\symdir

Can you give us a code example (batch or powershell is the same) to replicate your problem?

How to override existing symlink in Python3 if symlink already exists?

Cehcking the behavior of ln -nsf (with strace) will show that the command is executed by 2 systems calls:

  • Create symlink into the source file with a temporary file name in the destination folder.
  • Renaming the temporary file to the target file

The advantage of this approach (over remove/symlink) is that rename guarantee that at any point of time, the target file will either point to the old file, or to the new file.

Possible Python implementation (assuming safe to use ".new" as temporary link)

def symlink_force(target, link_name):
try:
temp_link = link_name + ".new"
os.remove(temp_link)
os.symlink(target, temp_link)
os.rename(temp_link, link_name)
except OSError e:
# Handle critical errors



Related Topics



Leave a reply



Submit