New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cd follows symlinks #3350
Comments
This was reported (and discussed to death) in #1957. The thing is, we're not doing anything special. We're using How is wine reacting to the PWD it is given? Would |
So, this won't work. It's not possible use symlinks to offer an "aliased" current working directory in fish, because fish will always resolve the real path it points at and place you there. So for example OS X if you |
@floam: Directory hardlinks aren't actually a thing. What might work is EDIT: Or pass the full path to wine. |
Hey man, I have directory hard links. I'd give up and just let whatever launches the game for me be a POSIX shell script that handles PWD normally. |
I'm not sure if I follow
Anyway, setting PWD env.variable works, but it's rather PITA, especially because path to that directory is 90 chars long. Running But considering that problem was "discussed to death" in closed issue, I'd guess this behavior is not going to be fixed. |
Your experiment only worked because the symlink was to a directory with the same parent as the link. It doesn't work in the general case. Try this example:
There's nothing to fix since the behavior isn't broken. It's merely different than what some other shells do. Both behaviors can be justified. The fish community simply believes that exposing the truth results in fewer problems. |
Sorry, I mixed that up. Do: mkdir -p /tmp/a/b
ln -s /tmp/a/b /tmp/link
cd /tmp/link # bash's PWD is now /tmp/link, fish would show /tmp/a/b
echo ../* # shows b
ls ../a # with bash's logic, this should show the contents of /tmp/link/../a (which is /tmp/a) - which would be "b" Really the point is that bash and basically everything else disagree on what "../" means.
Be less scared. When you do anything with relative paths, you can be confident that what fish shows you is what will happen. When you use "../SOMETHING", you can be sure that you could "cd .." and use "SOMETHING" instead. |
OK, I probably have a lot to say about this not being broken, but after reading through that linked issue I'm fairly sure I'be just repeating what others said. I ended up "fixing" it using |
It can be just as soon as folks are convinced. It's happened before. @kozec I actually share your preference. There is not really a unified front here holding discussion back. Somehow they allow me (for now) to commit to the repository! For me, anyhow, what fish does can be just as counterintuitive as bash, but more annoying, particularly when fish fails to let me "back out" out of a symlink the same way I came in and forces me to navigate out of whatever directory maze the symlinks dropped me into or remember directory history. Others have good reasons to not want my preference too, though. I can only bide my time. I hate to see threads like this close up - obviously I think it's useful to get the data points in 😄 |
I'd be open to changing this at some point in the future too - AFAIK nobody really loves the current behavior. That doesn't mean we should take bash's behavior wholesale, but it's worth thinking if we can make the UE better here. The "back out is annoying" stuff that floam mentions is real. |
Well, HOW? To me it seems like we either display and use the resolved path, or we display and use the unresolved one. Like I said, if you're gonna use relative paths with external commands, then it's nicer if you can count on the cwd matching - if I see the path is "SOMETHING/foo/bar/baz", and I want to remove the "spam" file next to foo, then I want to know that "../../../spam" will refer to it, without checking if foo, bar or baz are symlinks. To me, that strongly points towards resolving. The "annoying back out" is an issue, but it can be mitigated with e.g. |
There's got to be a lot of things we could do aside from these two options. You could change how you display it - to make it less jarring, when you are taken through the wormhole through the filesystem like this. There must be somehow with arrows or animation or something to show the user in their prompt how > cd /tmp/link
> pwd /private/tmp/a/b Maybe the interaction? With something that felt like a completion, one could somehow select the different universes where it "expands" one way versus the other as you're cd'ing. I dunno! Could have it show the real directories but cd .. could skips back through the logical parents instead of the absolute resolved ones? |
Meh - that's really lousy. That still makes you deal with becoming lost and so disoriented you had to pull out the CSI tools. I never use directory history, except for when something bad happens to me. To me, having the ground sort of ripped out from underneath you in a way that is going to assuredly not not permit you to get home without cd / or teleporting with directory history... it's a way worse problem than this "I need to be sure that |
AFAICT that's the only complaint of all I've read that I can take seriously. Most of the other arguments seem to involve profound misunderstandings about how symlinks work. Consider how many people ask that this be fixed rather than changed. They truly think fish is broken. And those misunderstandings are part of why I'm reluctant to emulate, say, bash's behavior. If I could be convinced that most people do in fact understand what is going on and know that using relative paths after cd'ing through a symlink won't work as they expect (in the general case) I'd be more comfortable making fish emulate bash in this regard. I wouldn't mind making I know I'm atypical since I've been using UNIX since the early 1980s and am thus used to living with shortcomings far more profound than this one. But like @faho I guess I don't see what's so hard about using |
That's a great point. Users think that it is fish that resolves symlinks, but of course the OS resolves symlinks whether you like it or not. Getting to bash's behavior does not mean taking anything out, it would mean adding new stuff in.
Yep. |
Yeah - where
> sudo ln -s (mktemp -d) /logically_here
> ./a.out
/private/var/folders/d6/t4zb8t9s4hb6835nktgtt4jc0000gp/T/tmp.VRDDSQfc⏎ ... is going to give us the unpleasant truth with these symlinks resolved without us doing anything extra. If we want to discern a physical working directory path from the logical one we need a little help from the shell here by recording something when we The problem on fish is that
Fish is undeniably adding something when $PWD gets realpath'd instead of just recorded during
Why? $PWD exists explicitly for this purpose, no? It should be set to the logical working directory path - it's only necessary that we make sure it is absolute and try to reduce ..'s inside. Why do we even need $PWD otherwise? Why do we not want it to take into account the context as to how the current directory was accessed? |
Do you mean $dirstack? Then that's actually wrong. |
I meant whatever I see when I type
|
Well, we're kinda debating if and why that is problematic. If it were the "logical working directory" (is that something you came up with or used elsewhere? either way, let's use that for now), then interaction with other tools is problematic. And the way it is now is something people aren't used to, and that makes e.g. Really, symlinks are weird. The weirdness isn't something fish has invented, it's the UNIX WAY^tm. The question is if there's something we can do to alleviate that weirdness. (Personally, it seems like it would be much more understandable if paths weren't canonicalized all the time in the system. But that's not the way it is and I may very well be missing something) But whatever that thing is, I don't think it's what bash is doing. It might be a better interface. An addition to |
I think that's POSIX/UNIX. |
"logical working directory" I guess I invented, they never actually put the terms together like that. I'm referring to -L on cd, where it logically resolves dot-dot. A logical current working directory, to me, is what we'd first need to know to hope to figure out the logical parent of our current working directory. It requires a $PWD that hasn't been canonicalized after our last
My actual goals aren't specifically -P or -L to even be options, just for this to work: sudo ln -s (mktemp -d) /logically_here
cd /logically_here
# $PWD is "/logically_here".
cd ..
# I'm back in / now It makes sense. Shouldn't need to dig into history or use pushd first. It'd (probably?) be easier if $PWD wasn't canonicalized. Why does fish have PWD as a read-only electric? We can't set it ourselves in cd.fish which is unfortunate. |
In the three decades I've been using UNIX I've never seen the phrase before now. There is no such thing. There is only the "current working directory". In fact
That is the default behavior. Getting the behavior of bash's The fish I have to say I'm also confused by the bash documentation for the |
Which is wrong, don't you think? Seems to me like it should say "Print an absolute pathname of the current working directory" - because there's not just one.
Uh, in bash
How can it break anything? It's longstanding standard behavior in UNIX for $PWD to be able to contain symlinks. If you wrote software that crashed when
Yes, all I meant by "logical" PWD is that the PWD is not canonicalized but allowed to contain symlinks for the current working directory as tracked by |
You just made my earlier point that people don't understand how UNIX file systems, and symlinks specifically, work. There is indeed "just one" canonical path to a given object in the classic UNIX file system model. I'm obviously ignoring esoteric extensions and things like chroot(2) which alter the idea of the file system root because they are not relevant to this discussion. But ignoring those unusual situations there is indeed a single path from the file system root to a given object that does not include symlinks.
I can't tell from reading the man page but given that so many bash refugees are asking us to emulate it I would bet that is the default. So what? As for it being POSIX standard behavior a) I haven't seen any references to the relevant standards doc, and b) fish explicitly states as an anti-goal blindly adhering to POSIX.
For bash. Not for fish let alone all shells as you imply. Since fish has historically canonicalized PWD changing that behavior can in fact confuse fish users and break existing scripts. Why do you insist on changing the behavior of PWD rather than simply introducing a new var that provides the "logical" (symlink including) path semantics? |
I'm just quoting the POSIX docs and my own experience with csh and ksh. The reason I asked is you mentioned compatibility issues and have been using UNIX for 30 years. I also can't tell from the manpages - I always get the stupid manpage for the builtins command. I had to check Can you tell me a single shell that doesn't take a PWD with symlinks? One?
Because it's the normal way to do it. |
Hey, friend... you are wrong. Maybe it's the fault of the documentation you were looking at - like I said they should change it from "the". ksh has the correct wording:
The
|
Yes, it does. But only when it uses the
I cannot make sense of that sentence. I would not expect any sane shell to blindly use the value of env var Your comments intrigued me enough to do some simple experiments on Apple's latest macOS Sierra beta release (a BSD derivative). The results were surprising and help explain why you, and others, are arguing for bash like behavior. Let's start a ksh93 shell and create a directory and two symlinks to that directory all with the same parent directory:
Now cd into one of the symlinks:
That
Wow! It blindly reports the lie. Whereas the GNU (Linux) pwd command reports the truth. Note that if we give it a different lie it reports the canonical path rather than parroting the
Now remove the alternate "z" symlink and observe what happens. Note that I have not done a
Note that up until I removed the "z" symlink the pwd command was happy to report it as the path that the user took to reach the "x" directory. Now it no longer does so. Yet I have not done a Note that at this point we are still in the "y" logical (i.e., symlink) path. What happens if we remove that symlink? Note that the ksh93 builtin still reports the now invalid logical path while the external command resorts to reporting the canonical, physical, path:
I'm sorry, but that behavior is just FUBAR. We should not emulate it. It was clearly implemented by people who were trying to paper over the issues created by symlinks. They failed except in trivial cases. It would have been better if they had recognized the problems with their "solution" and chosen to only alter the behavior of interactive uses of the |
Wipes tear from eye. Oh, it's a beautiful thing!
Fish can't even handle the
😞
Meh - what more could it do? $PWD is |
@krader1961 rereading your comments above, are you using ksh as an example of "FUBAR" here? Are you not liking it that when the symlink is deleted it is still showing that as the PWD? The deletion of some component of your path should not change the PWD, whether that component a symlink or a real directory that happened to have been removed. As I'm sure you're aware in Unix-like -OSes you can delete files that a process has a handle on - until that process dies that handle is good! Running We can check and see here, it's got the cwd fd open, so we know if we delete that, like normal files, we should expect nothing about the state to change due to this. He can keep using it until it's closed.
I don't know how well bash fares but given that it's probably gotten a decent amount of testing I'll guess it's more or less also able to proceed in those cases. |
I give up. Anyone else care to try explaining why most of the behaviors @floam likes are problematic? I'm also exceedingly concerned, @floam, when you say things like "That's a bug" after deleting the cwd and fish correctly reports that it can no longer determine the cwd. The error message could perhaps be more useful but it accurately reflects the situation. As someone who used to earn their living debugging Linux kernel crashes I suspect I have better knowledge of how open file descriptors interact with deleted file system objects than you do.
No, you cannot. I have no idea what you think you tested but you absolutely cannot |
I didn't really meant to start such discussion, but there is one thing I think is overlooked here. While I kinda like that high horse krader1961 is sitting on, I don't think that problem is what's "right" way to do it. Problem really is what user expects to happen, especially in something called "user-friendly command line shell." And after 10+ years of using and managing many Linux and some BSD installation, after 10+ years of using bash, bash and then mainly bash, this behavior is simply new trick I'm not going to learn :) I believe there may be much more people like me. |
I think you should expect it to work if it is already your CWD. If a chdir fails the CWD should be guaranteed to remain what it was before. Yeah, it impressed me. I'm probably stark raving mad but I like to say I just like stuff.
|
Hopefully this can help somebody ran into the same situation. |
https://github.com/externl/fish-symnav But seriously, I don't get an argument by @krader1961 that mungling with PWD makes some problems. PWD is readonly in fish, so it's impossible to mangle. If I'd like to resolve symlink, I could do Currently
(to be clear, my usecase for this |
Yeah, I'm now in favor of a virtualized path like other shells do. It creates some problems but is better on balance. |
This switches fish to a "virtual" PWD, where it no longer uses getcwd to discover its PWD but instead synthesizes it based on normalizing cd against the $PWD variable. Both pwd and $PWD contain the virtual path. pwd is taught about -P to return the physical path, and -L the logical path (which is the default). Fixes fish-shell#3350
This switches fish to a "virtual" PWD, where it no longer uses getcwd to discover its PWD but instead synthesizes it based on normalizing cd against the $PWD variable. Both pwd and $PWD contain the virtual path. pwd is taught about -P to return the physical path, and -L the logical path (which is the default). Fixes fish-shell#3350
This switches fish to a "virtual" PWD, where it no longer uses getcwd to discover its PWD but instead synthesizes it based on normalizing cd against the $PWD variable. Both pwd and $PWD contain the virtual path. pwd is taught about -P to return the physical path, and -L the logical path (which is the default). Fixes fish-shell#3350
This switches fish to a "virtual" PWD, where it no longer uses getcwd to discover its PWD but instead synthesizes it based on normalizing cd against the $PWD variable. Both pwd and $PWD contain the virtual path. pwd is taught about -P to return the physical path, and -L the logical path (which is the default). Fixes fish-shell#3350
This switches fish to a "virtual" PWD, where it no longer uses getcwd to discover its PWD but instead synthesizes it based on normalizing cd against the $PWD variable. Both pwd and $PWD contain the virtual path. pwd is taught about -P to return the physical path, and -L the logical path (which is the default). Fixes fish-shell#3350
This switches fish to a "virtual" PWD, where it no longer uses getcwd to discover its PWD but instead synthesizes it based on normalizing cd against the $PWD variable. Both pwd and $PWD contain the virtual path. pwd is taught about -P to return the physical path, and -L the logical path (which is the default). Fixes fish-shell#3350
Necessary due to the following update: fish-shell/fish-shell#3350
This issue surprised me today... setting aside all the above issues regarding virtual directory, what ... and the possibly true statement "nobody really loves the current behavior" ("user experience" is usually shortened to "UX" not "UE" btw) I liked the "old" behavior (pre-3.0.0) but also agree with eliminating sources of trouble. For anyone who wants a superficial "fix" with respect to how
|
Fun bug, took me a while to get it. After updating to fish v3, opening new terminals in tmux won't open the shell in the same path as the opener shell. But: - If I run a nested fish or bash shell inside the opener shell and then open a new shell, it does follow the correct path - Unsetting `default-command` from tmux would also restore the original intended behavior - Same behavior wouldn't occur if default shell is bash or zsh - Inspecting `${pane_current_path}` would suggest that the variable isn't even being updated at all when the shell is fish and default-command is set to "$SHELL"! Turns out, in the original setup, when a new terminal is opened by tmux, it launches the shell as `fish -c /usr/bin/fish`. So there is the parent fish shell and then that shell launches `/usr/bin/fish`. Any directory change done in this nested shell is not tracked by the parent fish shell instance, which is what tmux would read for `#{pane_current_path}`. This could be verified still by running `fish -c /usr/bin/fish`, cd'ing in this new shell, and then opening a new terminal to verify that the new path hasn't been followed. Running `bash -c /usr/bin/fish` however does not exhibit this behavior. Changing `default-command` to `exec $SHELL` eliminates this nesting, and hence tmux can read the appropriate path. Additionally, this results in a cleaner process tree as well regardless of which shell is being used. I am not sure if this is a bug or intended behavior with the new release of fish. Perhaps it is related to a change[1] in their new handling of current directory path. [1]: fish-shell/fish-shell#3350
@qtfkwk I was surprised too, and now use the following, which prints the real path after following a symlink: function cd --description 'cd and print real path when following a symlink'
builtin cd $argv
if test (pwd -P) != (pwd -L)
echo (pwd -P)
end
end Seems like a nice middle ground. Improvements are welcome ofc. BTW this does disable cd history (cdh, prevd, nextd), so to keep that intact it's better to modify the builtin by |
I too loved the old behavior. Conceptually, it prevented me from seeing symlinked directories as distinct from their source. An option to go back (akin to |
sh -c 'env HOME=$(mktemp -d) fish'
)?fish version installed (
fish --version
): fish, version 2.3.1OS/terminal used: Manjaro Linux, XFCE4-Terminal
Hello. I'm trying to launch application using Wine, what means I need path without non-ascii characters. Since application is installed to directory with Japanese name, I've created symlink and now I can't cd into it - for whatever crazy reason, cd follows that link and ends in original directory.
Reproduction steps
mkdir /tmp/any
)ln -s /tmp/any /tmp/link
)cd /tmp/link
)Expected results
Fish should navigate to link,
/tmp/link
Actual results
Cwd is set to target,
/tmp/any
The text was updated successfully, but these errors were encountered: