If a file or directory is named ~FOO then it is impossible to remove it and even more so dangerous to try. MSYS converts ~FOO to // instead so that using rm -rf ~FOO will in effect cause an rm -rf // to be issued.
Note that, in the example command offered, the shell would attempt to expand ~FOO as the home directory for user FOO, *before* handing it off to rm. Since MSYS doesn't associate users with specific home directories, (other than during execution of /etc/profile to initialise $HOME), tilde expansion should *always* fail gracefully, (except in the special case of a solitary tilde, which should and does expand to the value of $HOME), leaving the tilde expression unchanged; since it *is* changed there clearly is a bug. Just wanted to point out that it might lie within the bash.exe implementation, rather than in msys-core, (although it could equally well be in a service provided to bash by msys-1.0.dll).
As an interim (untested) work-around, 'rm -rf ./~FOO', or even simply wrapping ~FOO in quotes, (either double or single), should circumvent the tilde expansion, so allowing you to safely remove the errant directory; c.f.:
$ echo ~FOO
/
$ echo ./~FOO
./~FOO
$ echo '~FOO'
~FOO
$ echo "~FOO"
~FOO
Also, notice this anomaly when running in a subshell:
$ echo ~FOO
/home/keith
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Maybe bash should be compiled with -UHAVE_GETPWNAM. Else in lib/{tilde,readline}/tilde.c:390 getpwnam() is performed on the username part of the expanded string and then in line 414 "user_entry->pw_dir" is called to replace it with the user's home directory.
Maybe in lib/{tilde,readline}/tilde.c:390
#if defined (HAVE_GETPWNAM)
should get changed to
#if defined (HAVE_GETPWNAM) || defined __MSYS__
as MSYS simply does not support the concept of per-user directories.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The problem is in the getpwnam implementation in MSYS. For names other than the current user name, it should return NULL, instead of an entry filled with default values.
The next MSYS runtime release will have a fix.
Regards,
Cesar
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
However, may I suggest that - if HOME is not set for the current user - getpwnam should first try to return USERPROFILE before falling back to the hard-coded (and maybe non-existant) /home/${username}?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
PS: What happens with the fixed runtime (currently four slashes are returned):
$ unset HOME && echo ~ && echo ~$USERNAME && sh -c "echo ~" && sh -c "echo ~$USERNAME"
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> However, may I suggest that - if HOME is not set for the current user -
> getpwnam should first try to return USERPROFILE before falling back to the
> hard-coded (and maybe non-existant) /home/${username}?
This was discussed elsewhere. No! If HOME isn't set in the environment it is a bug of the environment and not MSYS. We don't support by default MSYS binaries being used in non-MSYS shells.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Fine, now the behaviour is *nearly* consistent with my Debian system.
With HOME set:
$ echo $HOME
/home/fabian
$ echo ~ && echo ~fabian && echo ~foo && sh -c "echo ~" && sh -c "echo ~fabian" && sh -c "echo ~foo"
/home/fabian
/home/fabian
~foo
/home/fabian
/home/fabian
~foo
With HOME unset:
$ unset HOME
$ echo ~ && echo ~fabian && echo ~foo && sh -c "echo ~" && sh -c "echo ~fabian" && sh -c "echo ~foo"
/home/fabian
/home/fabian
~foo
~
/home/fabian
~foo
> This was discussed elsewhere. No! If HOME isn't set in the environment
> it is a bug of the environment and not MSYS. We don't support by default
> MSYS binaries being used in non-MSYS shells.
I know, I know. I just wanted to suggest that the USERPROFILE variable may provide a more reasonable value as a fall-back than a hard-coded one. It is our host system's pendant to $HOME, it is assured to be set and its value is equally assured to be an existing directory. It is used by WinZsh (zsh-nt) as a fall-back when HOME isn't set, BTW.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You may wish to consider the comment I attached here:
http://thread.gmane.org/gmane.comp.gnu.mingw.user/37674/focus=37677
Note that, in the example command offered, the shell would attempt to expand ~FOO as the home directory for user FOO, *before* handing it off to rm. Since MSYS doesn't associate users with specific home directories, (other than during execution of /etc/profile to initialise $HOME), tilde expansion should *always* fail gracefully, (except in the special case of a solitary tilde, which should and does expand to the value of $HOME), leaving the tilde expression unchanged; since it *is* changed there clearly is a bug. Just wanted to point out that it might lie within the bash.exe implementation, rather than in msys-core, (although it could equally well be in a service provided to bash by msys-1.0.dll).
As an interim (untested) work-around, 'rm -rf ./~FOO', or even simply wrapping ~FOO in quotes, (either double or single), should circumvent the tilde expansion, so allowing you to safely remove the errant directory; c.f.:
$ echo ~FOO
/
$ echo ./~FOO
./~FOO
$ echo '~FOO'
~FOO
$ echo "~FOO"
~FOO
Also, notice this anomaly when running in a subshell:
$ echo ~FOO
/home/keith
Maybe bash should be compiled with -UHAVE_GETPWNAM. Else in lib/{tilde,readline}/tilde.c:390 getpwnam() is performed on the username part of the expanded string and then in line 414 "user_entry->pw_dir" is called to replace it with the user's home directory.
Maybe in lib/{tilde,readline}/tilde.c:390
#if defined (HAVE_GETPWNAM)
should get changed to
#if defined (HAVE_GETPWNAM) || defined __MSYS__
as MSYS simply does not support the concept of per-user directories.
> #if defined (HAVE_GETPWNAM) || defined __MSYS__
This should read
#if defined (HAVE_GETPWNAM) && !defined __MSYS__
Thanks for the report.
The problem is in the getpwnam implementation in MSYS. For names other than the current user name, it should return NULL, instead of an entry filled with default values.
The next MSYS runtime release will have a fix.
Regards,
Cesar
Fixed in CVS.
Before:
$ echo ~
/home/cstrauss
$ echo ~cstrauss
/
$ echo ~foo
/
After:
$ echo ~
/home/cstrauss
$ echo ~cstrauss
/home/cstrauss
$ echo ~foo
~foo
Regards,
Cesar
Dear Cesar,
with the current runtime the following happens:
admin@durin ~
$ echo ~foo
/
admin@durin ~
$ sh -c "echo ~foo"
/home/admin
What happens with the fixed runtime from CVS?
> What happens with the fixed runtime from CVS?
cstrauss@home ~
$ echo ~foo
~foo
cstrauss@home ~
$ sh -c "echo ~foo"
~foo
Great!
However, may I suggest that - if HOME is not set for the current user - getpwnam should first try to return USERPROFILE before falling back to the hard-coded (and maybe non-existant) /home/${username}?
PS: What happens with the fixed runtime (currently four slashes are returned):
$ unset HOME && echo ~ && echo ~$USERNAME && sh -c "echo ~" && sh -c "echo ~$USERNAME"
> However, may I suggest that - if HOME is not set for the current user -
> getpwnam should first try to return USERPROFILE before falling back to the
> hard-coded (and maybe non-existant) /home/${username}?
This was discussed elsewhere. No! If HOME isn't set in the environment it is a bug of the environment and not MSYS. We don't support by default MSYS binaries being used in non-MSYS shells.
>PS: What happens with the fixed runtime (currently four slashes are
> returned):
$ unset HOME && echo ~ && echo ~$USERNAME && sh -c "echo ~" && sh -c "echo ~$USERNAME"
/home/cstrauss
~cstrauss
/home/cstrauss
/home/cstrauss
Fine, now the behaviour is *nearly* consistent with my Debian system.
With HOME set:
$ echo $HOME
/home/fabian
$ echo ~ && echo ~fabian && echo ~foo && sh -c "echo ~" && sh -c "echo ~fabian" && sh -c "echo ~foo"
/home/fabian
/home/fabian
~foo
/home/fabian
/home/fabian
~foo
With HOME unset:
$ unset HOME
$ echo ~ && echo ~fabian && echo ~foo && sh -c "echo ~" && sh -c "echo ~fabian" && sh -c "echo ~foo"
/home/fabian
/home/fabian
~foo
~
/home/fabian
~foo
> This was discussed elsewhere. No! If HOME isn't set in the environment
> it is a bug of the environment and not MSYS. We don't support by default
> MSYS binaries being used in non-MSYS shells.
I know, I know. I just wanted to suggest that the USERPROFILE variable may provide a more reasonable value as a fall-back than a hard-coded one. It is our host system's pendant to $HOME, it is assured to be set and its value is equally assured to be an existing directory. It is used by WinZsh (zsh-nt) as a fall-back when HOME isn't set, BTW.
The fix for this issue was released with MSYS runtime 1.0.18,