Skip to content
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

Dir.chdir("~/filename")などで~が展開されるか否かの記述があった方がよい。 #2808

Open
hyuki opened this issue May 13, 2023 · 3 comments

Comments

@hyuki
Copy link

hyuki commented May 13, 2023

https://docs.ruby-lang.org/ja/latest/method/Dir/s/chdir.html

Dir.chdir("~/filename")などで~が展開されるか否かの記述があった方がよい。

Ruby 3.0.2では展開されないようだ。

Dir.chdir(File.expand_path("~/filename"))とすれば展開できる。

@tmyksj
Copy link
Contributor

tmyksj commented Nov 14, 2024

気になったので、いろいろ調べてみました。

まず RDoc には、 Dir.chdir("~/filename") などで ~ が展開される/されない、といった記述は見当たらないですね。
https://docs.ruby-lang.org/en/3.3/Dir.html#method-c-chdir

File.expand_path("~/filename") は、
s_expand_path v3_3_6 file.c#L4132-L4164
rb_file_s_expand_path v3_3_6 file.c#L4125-L4130
rb_file_expand_path v3_3_6 file.c#L4112-L4117
expand_path v3_3_6 file.c#L4099-L4100
rb_file_expand_path_internal v3_3_6 file.c#L3740-L4087

の流れで、最終的に ~ が展開されるようです。
WIN32 の場合は別の処理になるようですが…… rb_file_expand_path_internal v3_3_6 win32/file.c#L275-L582

Dir.chdir("~/filename") は、
dir_s_chdir v3_3_6 dir.c#L1108-L1189
chdir_path v3_3_6 dir.c#L1078-L1106
nogvl_chdir v3_3_6 dir.c#L1029-L1035

の流れで、 ~ が展開されないまま chdir(2) に渡されるようです。

実際に Dir.chdir("~/filename") が失敗する理由は Errno::ENOENT です。同じように chdir("~/filename")Errno::ENOENT で失敗します。

irb(main):001> Dir.chdir("~/filename")
(irb):1:in `chdir': No such file or directory @ chdir_path - ~/filename (Errno::ENOENT)
	from (irb):1:in `<main>'
	from <internal:kernel>:187:in `loop'
	from /usr/local/lib/ruby/gems/3.3.0/gems/irb-1.13.1/exe/irb:9:in `<top (required)>'
	from /usr/local/bin/irb:25:in `load'
	from /usr/local/bin/irb:25:in `<main>'
irb(main):002> 
$ cat << EOF > main.c
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
int main() {
  int ret = chdir("~/filename");
  printf("%d, %d, %d\n", ret, errno, ENOENT);
  return 0;
}
EOF
$ gcc -o main.out main.c
$ ./main.out 
-1, 2, 2
$

---

Dir.chdir("~/filename") などで ~ が展開されるか否かの記述があった方がよい。

RDoc には記述ないですが、実装は ~ を展開しないようなので、参考くらいの記述があるとちょうどよさそうに思いました。

@znz
Copy link
Member

znz commented Nov 14, 2024

シェル (たとえば bash) でも cd コマンドは展開しないので (展開するのはシェルのコマンドライン処理の方)、わざわざ説明を入れるなら、 chdir~ を展開するプログラミング言語の例がほしいです。

もしそういう言語がないのなら、間違いやすい例として実行例に入れるぐらいでもいいのかなと思いました。

$ mkdir -p ~/tmp
$ cd '~/tmp'
bash: cd: ~/tmp: No such file or directory

@tmyksj
Copy link
Contributor

tmyksj commented Nov 15, 2024

~ を展開する言語は、あまりないような気がします。

>>> import os
>>> os.chdir("~/filename")
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    os.chdir("~/filename")
    ~~~~~~~~^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '~/filename'
>>> 
php > chdir("~/filename");

Warning: chdir(): No such file or directory (errno 2) in php shell code on line 1
php > 
$ cat << EOF > main.go
package main
import (
    "log"
    "os"
)
func main() {
    err := os.Chdir("~/filename")
    if err != nil {
        log.Fatal(err)
    }
}
EOF
$ go run .
2024/11/15 13:56:15 chdir ~/filename: no such file or directory
exit status 1
$

もしそういう言語がないのなら、間違いやすい例として実行例に入れるぐらいでもいいのかなと思いました。

なるほど、実行例に入れるのはいい気がします。
追記する形で書くとすると、こんな感じでしょうか 🤔

Dir.chdir("/var/spool/mail")
p Dir.pwd                    #=> "/var/spool/mail"
Dir.chdir("/tmp") do
  p Dir.pwd                  #=> "/tmp"
end 
p Dir.pwd                    #=> "/var/spool/mail"

# ~ は展開されない
Dir.chdir('~/foo')           # => Errno::ENOENT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants