Tôi tò mò tại sao chúng ta không thể chuyển sang một giám đốc nhà của người dùng với một trong hai
$ cd ~"$USER"
hoặc là
$ cd ~${USER}
Tôi tò mò tại sao chúng ta không thể chuyển sang một giám đốc nhà của người dùng với một trong hai
$ cd ~"$USER"
hoặc là
$ cd ~${USER}
Câu trả lời:
Điều đó phụ thuộc rất nhiều vào lớp vỏ và thứ tự mở rộng được thực hiện trong các lớp vỏ đó.
~$user
mở rộng đến thư mục chính của người dùng có tên được lưu trữ $user
trong csh (nơi có ~user
tính năng đó ), AT & T ksh, zsh, fish.
Lưu ý tuy nhiên những biến thể sau:
$ u=daemon/xxx csh -c 'echo ~$u'
/usr/sbin/xxx # same in zsh/fish
$ u=daemon/xxx ksh93 -c 'echo ~$u'
~daemon/xxx
$ u=daemon/xxx csh -c 'echo ~"$u"'
Unknown user: daemon/xxx.
$ u=daemon/xxx zsh -c 'echo ~"$u"'
/usr/sbin/x # same in fish
$ u=" daemon" csh -c 'echo ~$u'
/home/stephane daemon
$ u=" daemon" zsh -c 'echo ~$u'
~ daemon # same in ksh/fish
$ u="/daemon" csh -c 'echo ~$u'
/home/stephane/daemon # same in zsh
$ u="/daemon" fish -c 'echo ~$u'
~/daemon # same in ksh
Nó mở rộng đến các thư mục chính của người dùng có tên theo nghĩa đen $user
trong bash
(với điều kiện là người dùng tồn tại, đó là rất khó xảy ra tất nhiên).
Và để không phải trong pdksh
, dash
, yash
, có lẽ vì họ không xem xét $user
để có một tên người dùng hợp lệ.
Mở rộng Tilde là một bước riêng biệt trong quá trình xử lý dòng lệnh. Nó xảy ra ngay trước khi mở rộng biến.
Nếu dấu ngã được theo sau bởi một dấu gạch chéo, nó sẽ mở rộng sang thư mục chính của người dùng có tên đang theo dấu ngã, ví dụ như trong ~otheruser
. Vì $USER
không được mở rộng tại thời điểm đó và vì không thể tương ứng với tên người dùng hợp lệ, dấu ngã không được mở rộng.
$USER
có thể là tên người dùng của người dùng hiện tại, vì vậy biểu thức của bạn có thể được thay thế bằng chỉ ~
.
Như các câu trả lời khác đã chỉ ra hành vi phụ thuộc vào thứ tự mà shell thực hiện ~
và $
mở rộng và liệu nó thậm chí sẽ làm cả hai cho cùng một từ.
Hành vi bạn đang tìm kiếm có thể đạt được bash
bằng một thay đổi rất nhỏ đối với lệnh của bạn. Đơn giản chỉ cần tiền tố lệnh với eval
.
eval "cd ~$USER"
sẽ thay đổi thư mục chính của người dùng được cung cấp bởi tên người dùng trong biến USER
, với điều kiện $USER
không chứa các ký tự đặc biệt cho trình bao (nếu có khả năng từ xa, bạn không nên chuyển nó thành đối số eval
vì điều đó sẽ nguy hiểm ) hoặc các /
ký tự và có một mục nhập cho người dùng đó trong cơ sở dữ liệu người dùng của hệ thống.
Một cách khác để tra cứu thư mục nhà của người dùng biến, nếu bạn đang sử dụng một trong các trình bao trong đó việc mở rộng dấu ngã xảy ra trước khi mở rộng biến, là với getent . Công cụ này tồn tại trên ít nhất Linux, Solaris và FreeBSD; Tôi không chắc nó phổ biến đến mức nào.
$ USER=bloggs
$ getent passwd "$USER" | cut -d: -f6
/home/b/bloggs
Như với mở rộng dấu ngã, điều này có thể không cung cấp cho bạn điều tương tự su - $USER -c 'echo $HOME'
sẽ in nếu bạn có đặc quyền để làm điều đó.
perl -le 'print((getpwnam shift)[7])' -- "$USER"
như có khả năng di động hơn một chút.
Vì OP khăng khăng đòi trả lời, nên đây là.
Hành vi của các lệnh đó (và nhiều thứ khác) phụ thuộc vào lớp vỏ cụ thể mà bạn đang sử dụng. Trừ khi bạn chỉ định loại vỏ cụ thể nào bạn sử dụng, có lẽ không thể đưa ra câu trả lời đơn giản.
Như một vấn đề thực tế, nếu bạn sử dụng tcsh, như tôi làm, cả hai biểu thức trong câu hỏi của OP (vì nó được viết khi tôi viết điều này - tôi không chịu trách nhiệm cho các chỉnh sửa trong tương lai!) Hoạt động hoàn toàn tốt. Tôi không biết những cái vỏ khác sẽ làm gì, vì tôi không sử dụng chúng. Vì vậy, có lẽ OP không biết nhiều về những gì có thể được thực hiện như họ nghĩ :-)