Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
can we have an option for cd to do a plain chdir()
- X-seq: zsh-workers 49744
- From: Stephane Chazelas <stephane@xxxxxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: can we have an option for cd to do a plain chdir()
- Date: Sun, 6 Feb 2022 17:44:06 +0000
- Archived-at: <https://zsh.org/workers/49744>
- List-id: <zsh-workers.zsh.org>
- Mail-followup-to: Zsh hackers list <zsh-workers@xxxxxxx>
I was surprised to see that after:
ln -s /proc/self/cwd/.. link; cd link
I ended up two directories up instead of one.
strace revealed:
$ strace -fe getcwd,readlink,chdir,fchdir zsh -c 'cd link'
readlink("/proc/self/fd/0", "/dev/pts/4", 4095) = 10
chdir("/home/chazelas/link") = 0
chdir("/home/chazelas/link") = 0
+++ exited with 0 +++
Not sure why the two chdir()s there.
That it prepends $PWD to the path is also a problem if the
current working directory has been renamed, but most shells do
that without -P.
It's better in that case with cd -P or with chaselinks:
$ strace -fe getcwd,readlink,chdir,fchdir zsh -c 'cd -P link'
readlink("/proc/self/fd/0", "/dev/pts/4", 4095) = 10
chdir("/home/chazelas/link") = 0
readlink("/home", 0x7ffe6ba34f00, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas", 0x7ffe6ba34f00, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas/link", "/proc/self/cwd/..", 4096) = 17
readlink("/proc", 0x7ffe6ba2fe70, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/self", "1000438", 4096) = 7
readlink("/proc/1000438", 0x7ffe6ba2ade0, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/1000438/cwd", "/home", 4096) = 5
readlink("/home", 0x7ffe6ba2ade0, 4096) = -1 EINVAL (Invalid argument)
chdir("..") = 0
chdir("/home") = 0
+++ exited with 0 +++
~$ strace -fe getcwd,readlink,chdir,fchdir zsh -o chaselinks -c 'cd link'
readlink("/proc/self/fd/0", "/dev/pts/4", 4095) = 10
readlink("/home", 0x7ffdfc3e0f40, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas", 0x7ffdfc3e0f40, 4096) = -1 EINVAL (Invalid argument)
chdir("/home/chazelas/link") = 0
readlink("/home", 0x7ffdfc3df960, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas", 0x7ffdfc3df960, 4096) = -1 EINVAL (Invalid argument)
readlink("/home/chazelas/link", "/proc/self/cwd/..", 4096) = 17
readlink("/proc", 0x7ffdfc3da8d0, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/self", "1002598", 4096) = 7
readlink("/proc/1002598", 0x7ffdfc3d5840, 4096) = -1 EINVAL (Invalid argument)
readlink("/proc/1002598/cwd", "/home", 4096) = 5
readlink("/home", 0x7ffdfc3d5840, 4096) = -1 EINVAL (Invalid argument)
chdir("..") = 0
chdir("/home") = 0
+++ exited with 0 +++
But that sounds a bit overkill and racy.
In scripts, you usually want your cd's to do plain chdir()s but
there are many things that get in the way:
- the need for -P to avoid the logical traversal
- the need to -- as usual for avoid problems with dirnames
starting with -
- CDPATH (it is inherited from the environment but at least when
not in POSIX mode, that doesn't take precedence over actual
relative path).
- The "-" string that is taken as $OLDPWD
- Also in zsh, the -n +n ones.
- and then there's that special fancy chasing of symlinks
So, to do an actual chdir, we need something like:
chdir() {
case $1 in
(/*) cd -P "$1";;
('') print -u2 "not sure out to chdir to an empty string";;
(*) cd -P "./$1";;
esac
}
Which addresses the first 5 points, but not the 6th.
It would be nice if we could just do for instance cd -r -- $dir
which would just a do chdir($dir) and set $PWD to getcwd() if
successful.
(or have chdir (which atm exits as a builtin for tcsh junkies I
suppose) do that and not take any option).
What do you think?
--
Stephane
Messages sorted by:
Reverse Date,
Date,
Thread,
Author