What does "cd .." and "pwd" really mean when you have softlinks involved? [closed] - linux

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 8 years ago.
Improve this question
See the Unix commands below.
When we are dealing with soft-links, there can be multiple paths to the root from each directory.
So in this case, how is pwd and cd .. calculated? It means that directory paths are no longer stateless, right?
$ cd ~
$ mkdir a b
$ cd a
$ ln -s ~/b b
$ cd b
$ pwd
/home/myuser/a/b
$ cd ..
$ pwd
/home/myuser/a

Look at this example:
[myuser#test ~]$ pwd
/home/myuser
[myuser#test ~]$ mkdir a b
[myuser#test ~]$ cd a
[myuser#test a]$ ln -s ~/b b
[myuser#test a]$ cd b
[myuser#test b]$ pwd
/home/myuser/a/b
[myuser#test b]$ pwd -P
/home/myuser/b
[myuser#test b]$ echo $$
2432
[myuser#test b]$ ls -l /proc/2432/cwd
lrwxrwxrwx 1 myuser myuser 0 Oct 4 04:10 /proc/2432/cwd -> /home/myuser/b
[myuser#test b]$
[myuser#test b]$
[myuser#test b]$ pwd
/home/myuser/a/b
[myuser#test b]$ cd -P ..
[myuser#test ~]$ pwd
/home/myuser
[myuser#test ~]$
[myuser#test ~]$ env | grep "PWD"
PWD=/home/myuser
OLDPWD=/home/myuser/a/b
See option -P to cd from bash manual:
-P If set, the shell does not follow symbolic links when executing commands such as cd that
change the current working directory. It uses the physical directory structure instead.
By default, bash follows the logical chain of directories when performing commands which
change the current directory.
As you can see, the current dir keeps by kernel is your real dir (/proc/2432/cwd -> /home/myuser/b) but bash can do whatever wants follow symbolic links or not,
because cd is bash internal command.

The commands are always computed based on the actual(resolved) directory behind the soft link.
When you do
$ cd b ; you end up in the directory pointed by b
Any command from here is resolved based on this new location

Related

How can I enter the directory with prefix '-t'

By mistake, I create a directory with the prefix '-t' on a Linux server. For example, -train-20200514-081411. When I want to cd -train-20200514-081411, there is an error:
-bash: cd: -t: invalid option
cd: usage: cd [-L|-P] [dir]
So in this case, how can I use this directory?
Thank you very much for any help!
You can use:
cd -- -train-20200514-081411
The -- tells bash not to interpret any more items as flags, example transcript below:
[~]: mkdir -- -turkey; ls
-turkey other_file.txt
[~]: cd -- -turkey
[~/-turkey]: cd ..
[~]: rmdir -- -turkey; ls
other_file.txt

Why ln -sf does not overwrite existing link to directory [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 4 years ago.
Improve this question
According to documentation, command ln -f removes existing destination file. Does this mean that if I create a symlink, -f should remove of overwrite any existing symlink at destination?
I have a symlink, say, L, pointing to DIR1 and type ln -sf DIR2 L. But L still points to DIR1. Only after rm L this command creates a link pointing to DIR2.
With symlinks to files it behaves as expected.
What's wrong with links to directories?
(bash 4.3.48 on Ubuntu 16.04.2 LTS and Windows WSL)
When you run:
ln -sf DIR2 L
This is creating a symlink inside DIR1 cause L points to DIR1 and ln dereferences it, creating L/DIR2 -> DIR1.
The following:
rm -fr DIR1 DIR2 L
mkdir DIR1 DIR2
ln -v -s DIR1 L
ls -la L
ln -v -f -s DIR2 L
ls -la L
will output:
'L' -> 'DIR1'
lrwxrwxrwx 1 runner runner 4 Oct 21 18:13 L -> DIR1
'L/DIR2' -> 'DIR2'
lrwxrwxrwx 1 runner runner 4 Oct 21 18:13 L -> DIR1
To handle that, use the --no-dereference option as indicated in answer in this thread on superuser.com.

Can't SSH to keep latest 5 folders and delete the older folders [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 5 years ago.
Improve this question
Currently I am using ls -1t | tail -n +6 | xargs rm -rf and it works fine at the server itself. But when I try it through ssh using root in a bash script, it doesn't run/work.
This is the line I am using : ssh -q -oStrictHostKeyChecking=no -oConnectTimeout=1 root#$host "sudo cd /path/to/folder && sudo ls -1t | tail -n +6 | xargs rm -rf"
May I know what's the issue here?
root#$host suggests that you're already logged in as root, so using sudo is redundant here.
cd /path/to/folder && ls -1t | tail -n +6 | xargs rm -rf
should do the trick.
But this is only safe if you exactly know that /path/to/folder can not contain any files with possibly dangerous characters in their names. For example a file named ..\n or similar would cause the whole directory to be deleted.
The reason your original example does not work is that sudo executes a program, not a series of shell commands. Also cd is not a program but a shell builtin, so it can't be executed through sudo, as this wouldn't really make sense, the directory change would be lost after cd returned. If that worked, then in your case the first statement (sudo cd /path/to/folder) would execute successfully, and then the second one (sudo ls -1t | tail -n +6 | xargs rm -rf) would execute in the current directory, but only the ls command as root, the rest as the current user.
To execute the whole command line through sudo
sudo sh -c "cd /path/to/folder && ls -1t | tail -n +6 | xargs rm -rf"
Or, if the current user has access rights for /path/to/folder, then actually only the last part needs to be executed as root:
cd /path/to/folder && ls -1t | tail -n +6 | sudo xargs rm -rf

gnu linux why does command "cd xyzdir && rm -rf abcfilename" fail?

$ touch /tmp/abcd
$ ls -l /tmp/abcd
--w--w--w- 1 dinesh users 0 Oct 16 23:49 /tmp/abcd
$ x="cd /tmp && rm -rf abcd"
$ $x
$ pwd
/tmp
$ ls -l /tmp/abcd
--w--w--w- 1 dinesh users 0 Oct 16 23:49 /tmp/abcd
OTOH using x="cd /tmp; rm -rf abcd" works as I expected. So, what's wrong with my other approach because I want to be sure I am in that directory? $? always returns 0.
I guess always an oppty to learn. Thanks a lot. Dinesh
$ uname -a
Linux test-host 3.0.93-0.5-default #1 SMP Tue Aug 27 08:17:02 UTC 2013 (925d406) x86_64 x86_64 x86_64 GNU/Linux
We get the idea if we turn on trace output (0> is the prompt).
0>set -x
0>$x
+ cd /tmp '&&' rm -rf abcd
We see that && rm -rf abcd are just passed as extra arguments to the cd command. Obviously the parsing of && as a command list operator only takes place before parameter expansion, no more after $x has been substituted. Oddly, cd doesn't complain about the extra arguments - try:
cd . dumb and dumber
Logically
eval $x
works as desired.
OTOH using x="cd /tmp; rm -rf abcd" works as I expected.
You must be mistaken here.
0>$x
+ cd '/tmp;' rm -rf abcd
bash: cd: /tmp;: No such file or directory
Just as &&, ; is not parsed as a control operator here, but simply as the last character of the directory name /tmp; - consequently yielding an error.

Does $PWD always equal $(realpath .)

Given
A modern Linux/UNIX/OSX (w/ realpath)
bash 4+ (even on OSX)
Is
"$PWD" == "$(realpath .)"
Always true?
It's pretty easy to test that this is not always the case.
$ mkdir /tmp/realdir
$ cd /tmp/realdir
$ echo $PWD
/tmp/realdir
$ ln -s realdir /tmp/fakedir
$ cd /tmp/fakedir
$ echo $PWD
/tmp/fakedir
$ realpath .
/tmp/realdir
so no, $PWD is not always the same as $(realpath .).
The bash manual indicates that the PWD variable is set by the built-in cd command. the default behaviour of cd is:
symbolic links are followed by default or with the -L option
This means that if you cd into a symlink the variable gets resolved relative to the symlink, not relative to the physical path. You can change this behavior for a cd command by using the -P option. This will cause it to report the physical directory in the PWD variable:
$ cd -P /tmp/fakedir
$ echo $PWD
/tmp/realdir
You can change the default behavior of bash using the -P option:
$ set -P
$ cd /tmp/fakedir
$ echo $PWD
/tmp/realdir
$ set +P
$ cd /tmp/fakedir
$ echo $PWD
/tmp/fakedir
This is of course notwithstanding the fact that you can assign anything you want to the PWD variable after performing a cd and it takes that value:
$ cd /tmp/fakedir
$ PWD=/i/love/cake
$ echo $PWD
/i/love/cake
but that's not really what you were asking.
It is not necessarily the case even when symbolic links are not used and PWD is not set by the user:
vinc17#xvii:~$ mkdir my_dir
vinc17#xvii:~$ cd my_dir
vinc17#xvii:~/my_dir$ rmdir ../my_dir
vinc17#xvii:~/my_dir$ echo $PWD
/home/vinc17/my_dir
vinc17#xvii:~/my_dir$ realpath .
.: No such file or directory
Note that under zsh, ${${:-.}:A} still gives the same answer as $PWD (the zshexpn(1) man page says about the A modifier: "Note that the transformation takes place even if the file or any intervening directories do not exist.").
Note that however, $PWD contains obsolete information. Using it may be a bad idea if some other process can remove the directory. Consider the following script:
rm -rf my_dir
mkdir my_dir
cd my_dir
echo 1 > file
cat $PWD/file
rm -r ../my_dir
mkdir ../my_dir
echo 2 > ../my_dir/file
cat ./file
cat $PWD/file
rm -r ../my_dir
It will output:
1
cat: ./file: No such file or directory
2
i.e. $PWD/file has changed.

Resources