Điều quan trọng cần hiểu là ~
mở rộng là một tính năng của shell (của một số shell), nó không phải là một nhân vật kỳ diệu hơn có nghĩa là thư mục nhà của bạn bất cứ nơi nào nó được sử dụng.
Nó được mở rộng (bởi shell, là một ứng dụng được sử dụng để giải thích các dòng lệnh), giống như $var
được mở rộng thành giá trị của nó trong một số điều kiện khi được sử dụng trong một dòng lệnh shell trước khi lệnh được thực thi.
Tính năng đó lần đầu tiên xuất hiện trong vỏ C vào cuối những năm 1970 (vỏ Bourne không có nó, cũng không phải là vỏ trước của nó), sau đó được thêm vào vỏ Korn (vỏ mới hơn được chế tạo trên vỏ Bourne trong vỏ Những năm 80). Cuối cùng, nó đã được chuẩn hóa bởi POSIX và hiện có sẵn trong hầu hết các shell bao gồm cả những cái không phải POSIX như fish
.
Bởi vì nó được sử dụng rộng rãi như vậy trong shell, một số ứng dụng không shell cũng nhận ra nó có nghĩa là thư mục chính. Đó là trường hợp của nhiều ứng dụng trong các tập tin cấu hình của họ hoặc họ riêng dòng lệnh ( mutt
, slrn
, vim
...).
bash
cụ thể (là vỏ của dự án GNU và được sử dụng rộng rãi trong nhiều hệ điều hành dựa trên Linux), khi được gọi là sh
, chủ yếu tuân theo các quy tắc POSIX về ~
mở rộng và trong các khu vực không được chỉ định bởi POSIX, hoạt động chủ yếu như vỏ Korn (của mà nó là một bản sao một phần).
Mặc dù $var
được mở rộng ở hầu hết các nơi (ngoại trừ bên trong các trích dẫn đơn), ~
việc mở rộng, suy nghĩ lại chỉ được mở rộng trong một vài điều kiện cụ thể.
Nó được mở rộng khi trên đối số của chính nó trong bối cảnh danh sách, trong bối cảnh nơi một chuỗi được mong đợi.
Dưới đây là một vài ví dụ về nơi nó được mở rộng tại bash
:
cmd arg ~ other arg
var=~
var=x:~:x
(được POSIX yêu cầu, được sử dụng cho các biến như PATH
, MANPATH
...)
for i in ~
[[ ~ = text ]]
[[ text = ~ ]]
(việc mở rộng ~
được lấy làm mẫu trong AT & T ksh
nhưng không bash
kể từ 4.0).
case ~ in ~) ...
${var#~}
(mặc dù không có trong một số vỏ khác)
cmd foo=~
(mặc dù không phải khi được gọi là sh
và chỉ khi những gì ở bên trái của =
nó có hình dạng như một bash
tên biến không được trích dẫn )
cmd ~/x
(rõ ràng là yêu cầu của POSIX)
cmd ~:x
(nhưng không x:~:x
hoặc x-~-x
)
a[~]=foo; echo "${a[~]} $((a[~]))"
(không phải trong một số vỏ khác)
Dưới đây là một vài ví dụ mà nó không được mở rộng:
echo "~" '~'
echo ~@ ~~
(cũng lưu ý rằng ~u
có nghĩa là mở rộng sang thư mục chính của người dùng u
).
echo @~
(( HOME == ~ ))
, $(( var + ~ ))
- với
extglob
: case $var in @(~|other))...
(mặc dù case $var in ~|other)
vẫn ổn).
./configure --prefix=~
(như --prefix
không phải là một tên biến hợp lệ)
cmd "foo"=~
(trong bash
, vì các trích dẫn).
- khi được gọi là
sh
: export "foo"=~
, env JAVA_HOME=~ cmd
...
Đối với những gì nó mở rộng thành: ~
một mình mở rộng đến nội dung của HOME
biến hoặc khi nó không được đặt, vào thư mục chính của người dùng hiện tại trong cơ sở dữ liệu tài khoản (như một phần mở rộng vì POSIX không xác định hành vi đó).
Cần lưu ý rằng trong ksh88 và bash
các phiên bản trước 4.0, việc mở rộng dấu ngã đã trải qua quá trình toàn cầu hóa (tạo tên tệp) trong bối cảnh danh sách:
$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
Đó không phải là một vấn đề trong các trường hợp thông thường.
Lưu ý rằng vì nó được mở rộng, cảnh báo tương tự được áp dụng như các hình thức mở rộng khác.
cd ~
Không hoạt động nếu $HOME
bắt đầu với -
hoặc chứa ..
các thành phần. Vì vậy, mặc dù rất khó có thể tạo ra bất kỳ sự khác biệt nào, nhưng nói đúng ra, người ta nên viết:
cd -P -- ~
Hoặc thậm chí:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(để bao gồm các giá trị $HOME
như -
, +2
...) hoặc đơn giản là:
cd
(như cd
đưa bạn đến thư mục nhà của bạn mà không có bất kỳ đối số)
Các vỏ khác có bản ~
mở rộng tiên tiến hơn . Chẳng hạn, trong zsh
, chúng ta có:
~4
, ~-
, ~-2
(Với hoàn) được sử dụng để mở rộng thư mục trong đống thư mục của bạn (những nơi bạn đã cd
đến trước đó).
- thư mục có tên động . Bạn có thể xác định cơ chế của riêng mình để quyết định cách
~something
mở rộng.
~
sẽ tương đương với$HOME
trong bất kỳ môi trường POSIX nào; nhưng tôi có thể sai