Mengapa saya tidak bisa melakukan cd ke tilde yang dikutip ('~')?


32

Menulis skrip pertama saya jadi saya yakin ini adalah pertanyaan dasar, tetapi bisakah seseorang tolong jelaskan kepada saya mengapa saya bisa:

cd ~
cd bin
cd ~/bin
cd 'bin'

Tapi tidak

cd '~'
cd '~/bin'

Saya perlu ke cdjalur direktori dengan spasi di salah satu nama direktori, jadi saya perlu tanda kutip (ini Windows di Program Filesbawah anggur). Saya bisa mengatasinya dengan dua cdperintah, tetapi mengapa saya tidak bisa memberi ~tanda kutip?

Jika saya mengetik cd '~'(atau cd "~") saya mendapatkan:

bash: cd: ~: No such file or directory

29
Tanyakan pada diri sendiri ini: jika jika tidak bekerja seperti itu, bagaimana Anda akan cdmasuk ke direktori bernama ~?
Jörg W Mittag

2
Sebagai sidenote, jika Anda menulis skrip, Anda sebaiknya menggunakan jalur absolut dan menghindari semuanya cd. Gunakan variabel untuk menyimpan nama path yang tidak ingin Anda ketikkan beberapa kali, misalnyapf=~/.wine/drive_c/Program\ Files/; cp /path/to/file "$pf"
makanan penutup

8
@ jamesqf: Mengapa sistem yang masuk akal dianggap tahu lebih baik daripada saya tentang apa yang ingin saya beri nama file dan direktori saya? Juga, saya tidak pernah mengerti mengapa Unix pergi dengan pensinyalan in-band ajaib pemisah komponen jalur dan terminator jalur. Apa yang salah dengan nama file / direktori /atau NUL?
Jörg W Mittag

3
@ JörgWMittag mungkincd ./~
k_g

2
@ jamesqf Hanya untuk mencatat bahwa secara historis, sistem file Unix mengizinkan karakter apa pun dalam nama file kecuali '/' (pemisah jalur) dan '\ 0' (NUL - char-termination-string char) - seperti yang dicatat Jorg. Tidak ada batasan lain. Ada banyak implementasi sistem file Unix, jadi memperkenalkan pembatasan pada salah satu dari mereka akan merusak kompatibilitas dan meningkatkan kompleksitas - dan dipandang sebagai "aneh"! Dan ekspansi '~' hanya diperkenalkan secara komparatif baru-baru ini di csh dan lebih luas di bash, file / dir dengan chars '~' tidak diketahui (mis. Myfile ~ sebagai cadangan untuk myfile).
SusanW

Jawaban:


78

Seperti yang dicatat @karel dalam jawabannya, ~adalah karakter khusus dan diperluas oleh Bash ke direktori home pengguna saat ini. Lihat manual Bash pada "Ekspansi Tilde" , atau cari judul "Ekspansi Tilde" di halaman manual ( man bash).

Setiap jenis kutipan di sekitar ~mencegah ekspansi tilde ini.


Untuk menjawab pertanyaan Anda tentang bagaimana Anda masih bisa menggunakannya cdke direktori dengan spasi di namanya, ada beberapa alternatif:

  • Hilangkan tanda kutip dan hindari spasi dengan garis miring terbalik sebagai gantinya:

    cd ~/foo/spaces\ are\ cool/bar
  • Mengutip sisa dari jalan, tetapi hilangkan mereka di sekitar tilde dan garis miring pertama:

    cd ~/"foo/spaces are cool/bar"

    Seperti yang Anda lihat, Anda dapat menggabungkan string yang dikutip dan tidak dikutip di Bash dengan hanya menulisnya berdampingan tanpa spasi di antaranya.

  • Gunakan variabel lingkungan $HOMEalih-alih tilde, yang masih diperluas dalam "tanda kutip ganda" (tapi bukan 'tanda kutip tunggal'):

    cd "$HOME/foo/spaces are cool/bar"

3
@rexkogitans ~'/...'tidak akan berfungsi dan tidak sesuai dengan jawaban ini. ~/'...'atau ~/"..."akan bekerja.
hvd

tld; dr: karena itu sintaks shell
Sergiy Kolodyazhnyy

@ DVD terima kasih. Memperbaiki kesalahan ketik. Ini adalah jawaban yang paling lengkap dan juga menjelaskan bagaimana menyelesaikan apa yang OP ingin lakukan. ~/'path'adalah cara untuk pergi.
rexkogitans

1
@ Hvd hanya sedikit rasa ingin tahu, mengapa tidak ~'/...'berhasil? Garis miring bukanlah karakter khusus sehingga sepertinya harus bekerja di dalam atau di luar tanda kutip.
Kodos Johnson

6
@KodosJohnson Lihatlah bagian manual Bash tentang "Ekspansi Tilde". Paragraf yang relevan juga dikutip dalam jawaban pencuci mulut di bawah ini. TL; DR: Perluasan Tilde terjadi jika karakter pertama dalam sebuah kata adalah tanda kutip tanpa tanda kutip, maka segala sesuatu di antara tanda gelombang dan tanda kutip tanpa tanda kutip berikutnya dianggap sebagai "awalan tilde". Jika awalan ini bukan hal yang valid seperti +, -, angka, atau nama pengguna (tanda kutip di sana juga tidak diperbolehkan), ekspansi gagal dan Anda mendapatkan karakter ~ literal.
Byte Commander

17

~ adalah karakter khusus yang diartikan oleh shell sebagai direktori home pengguna yang login. '~' ditafsirkan oleh shell sebagai karakter ~ literal, bukan sebagai direktori home pengguna yang login karena melampirkan string di dalam dua karakter kutipan tunggal menghasilkan string diinterpretasikan sebagai string teks literal.


~bukan alias dalam arti bashmenafsirkannya: Alias ​​memungkinkan string untuk diganti dengan kata ketika digunakan sebagai kata pertama dari perintah sederhana. . Seperti yang saya jelaskan dalam jawaban saya di bawah, ini agak ekspansi.
hidangan penutup

15

Ini adalah bashfitur yang disebut Ekspansi Tilde . Mengutip man bash:

Jika sebuah kata dimulai dengan karakter tilde yang tidak dikutip (`~ '), semua karakter yang mendahului slash tanpa tanda kutip pertama (atau semua karakter, jika tidak ada slash yang tidak dikutip) dianggap sebagai awalan tilde. Jika tidak ada karakter dalam awalan tilde yang dikutip, karakter dalam awalan tilde yang mengikuti tilde dianggap sebagai nama login yang memungkinkan. Jika nama login ini adalah string nol, tilde diganti dengan nilai parameter shell HOME. Jika HOME tidak disetel, direktori home dari pengguna yang menjalankan shell diganti.

Agar ekspansi berfungsi, karakter tilde ~perlu dikuotasi, jika karakter tersebut diambil secara harfiah dan cdgagal jika tidak ada direktori bernama ~present di direktori saat ini. Lihat jawaban yang menarik ini untuk penjelasan tentang cara mengutip bash. Jika Anda perlu mengutip bagian dari jalur, Anda dapat:

  1. kutip setidaknya karakter yang perlu kutip dengan kutip tunggal, mis

    ~/dir' 'with' 'spaces/

    atau

    ~/'dir with spaces/'
  2. kutip setidaknya karakter yang perlu kutip dengan kutip ganda, mis

    ~/dir" "with" "spaces/

    atau

    ~/"dir with spaces/"
  3. hanya mengutip karakter yang perlu kutip dengan garis miring terbalik, mis

    ~/dir\ with\ spaces/

Tilde Expansion memiliki beberapa fitur yang lebih menarik, misalnya:

  • ~+memperluas ke nilai PWD, yaitu direktori kerja saat ini
  • ~-memperluas ke nilai OLDPWD, yaitu direktori kerja sebelumnya
  • ~john memperluas ke direktori home yang terkait dengan nama login "john"

Kebetulan, tidak masalah untuk 'overquote' dengan backslash juga; misalnya $ touch a; cd \a,. (Saya pikir ini mungkin akan bermasalah cd \n, tetapi percobaan setidaknya pada versi saya bashmenunjukkan itu berfungsi dengan baik.)
LSpice

1

Jelajahi menggunakan echoperintah

Cara termudah untuk mengeksplorasi cara kerja bash adalah dengan echoperintah. Dalam hal ~penggunaan ini:

$ echo ~
/home/rick
$ echo '~'
~
$ echo "~"
~
$ echo `~`
bash: /home/rick: Is a directory

Seperti yang Anda lihat, ketika Anda mengutip tunggal atau menggunakan tanda kutip ganda di ~sekitarnya ditafsirkan secara harfiah sebagai string dan tidak diperluas sebagai variabel. Ketika Anda menggunakan backticks (`) dieksekusi sebagai perintah dan menghasilkan pesan kesalahan.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.