Karakter apa yang perlu diloloskan dalam file tanpa tanda kutip?

12

Saya memiliki shell / terminal berbasis browser yang mengeksekusi perintah bash dan saya keluar dari spasi tetapi ternyata tanda kurung juga harus diloloskan. Apa karakter lain yang perlu diloloskan untuk nama file yang tidak ada dalam tanda kutip?

jcubic
sumber
Sama sekali tidak jelas apa yang Anda coba lakukan. Dan apa yang harus dilakukan pelengkapan otomatis dengan apa pun?
Michael Vehrs
@MichaelVehrs Saya memiliki perintah mv filename filename-foodalam bash, karakter mana yang harus saya hindari, selain spasi dan tanda kurung?
jcubic
@MichaelVehrs menghapus penyebutan autocomplete.
jcubic
Pada dasarnya, semua karakter meta shell, seperti spasi putih, shell global, peristiwa sejarah. Untuk alasan ini, Anda harus mengutip seluruh nama file, bukan melarikan diri karakter individu: mv "$filename" "$newname".
Michael Vehrs
@MichaelVehrs Saya tahu bahwa mengutip akan menyelesaikan masalah dengan melarikan diri tetapi saya harus menggunakan nama file tanpa tanda kutip. Saya memiliki terminal emulator dan harus berfungsi ketika pengguna tidak menggunakan tanda kutip.
jcubic

Jawaban:

22

Solusi sederhana adalah dengan menempatkan tanda kutip tunggal ( ') di awal dan tanda kutip tunggal lainnya di akhir, dan mengganti setiap 'karakter di dalam nama file dengan urutan 4 karakter '\''. Semua karakter kehilangan makna khusus mereka di dalam string yang dikutip tunggal, kecuali 'dirinya sendiri yang menandai akhir string. Urutan '\''mengakhiri literal yang dikutip tunggal, segera diikuti oleh kutipan tunggal yang dikutip, dan membuka literal yang dikutip tunggal. Demikian nama filenya

This file's name has some weird characters!
Will you manage to escape them?

dapat dikutip sebagai berikut:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'

Kutipan ganda memiliki aturan pelolosan yang lebih kompleks dan tidak memungkinkan Anda untuk menyertakan tanda seru !jika penggantian riwayat diaktifkan, jadi saya tidak akan mempertimbangkannya lebih lanjut.

Pendekatan alternatif adalah melindungi karakter dengan garis miring terbalik. Ini berfungsi untuk setiap karakter kecuali baris baru; untuk baris baru, memasukkannya ke dalam tanda kutip tunggal (atau tanda kutip ganda) adalah satu-satunya solusi. Jika Anda ingin meminimalkan jumlah garis miring terbalik untuk menyajikan nama yang dikutip kepada pengguna, Anda dapat membatasi itu ke tempat-tempat di mana garis miring terbalik diperlukan; namun, semakin banyak backslash yang Anda hilangkan, semakin Anda berisiko melupakan yang dibutuhkan. Huruf, digit, dan karakter non-ASCII selalu ok¹. Kutip spasi putih dan tanda baca setiap kali Anda tidak yakin.

Dengan shell yang khas (ksh, bash atau zsh), Anda perlu mengutip karakter berikut setidaknya dalam beberapa keadaan.

  • Spasi putih (spasi, tab, baris baru - mengingat baris baru tidak dapat dikutip dengan garis miring terbalik).
  • ! - ekspansi sejarah.
  • " - sintaks shell.
  • #- komentar mulai ketika didahului oleh whitespace; zsh wildcard.
  • $ - sintaks shell.
  • & - sintaks shell.
  • ' - sintaks shell.
  • (- bahkan di tengah kata: ksh extended glob (juga tersedia dalam bash dan zsh); zsh wildcard.
  • )(lihat ()
  • * - sh wildcard.
  • , - hanya di dalam ekspansi brace.
  • ; - sintaks shell.
  • < - sintaks shell.
  • = - di zsh, ketika itu di awal nama file (ekspansi nama file dengan pencarian PATH).
  • > - sintaks shell.
  • ? - sh wildcard.
  • [ - sh wildcard.
  • \ - sintaks shell.
  • ] - Anda bisa lolos tanpa tanda kutip.
  • ^- ekspansi sejarah; zsh wildcard.
  • ` - sintaks shell.
  • { - ekspansi brace.
  • | - sintaks shell.
  • } - perlu melarikan diri di zsh, shell lain lebih lunak ketika tidak ada brace pembuka yang cocok.
  • ~- Ekspansi direktori home ketika itu di awal nama file; zsh wildcard; selalu aman saat itu adalah karakter terakhir.

Beberapa karakter lagi terkadang memerlukan penanganan khusus:

  • -tidak khusus untuk shell, tetapi ketika itu di awal argumen perintah, itu menunjukkan opsi. Itu tidak dapat dilindungi dengan tanda kutip karena penanganan khusus ada di perintah, bukan di shell. Untuk melindungi nama file yang dimulai dengan -, Anda bisa meletakkannya ./sebelum ini - dengan cara ini masih file yang sama, tetapi argumen tidak dimulai dengan -lagi.
  • .itu sendiri tidak istimewa, tetapi file dot dikecualikan dari *gumpalan secara default.
  • :tidak khusus untuk shell, tetapi beberapa perintah menguraikannya secara khusus, misalnya untuk menunjukkan file jarak jauh ( hostname:filename). Konsultasikan dokumentasi perintah untuk melihat bagaimana cara mengatasi file nams yang berisi titik dua.

¹ Kecuali jika pengguna telah mengkonfigurasi karakter ekspansi sejarah alternatif. Beberapa kerang memungkinkan ini. Ini adalah alasan lain untuk menggunakan tanda kutip tunggal daripada backslash.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Newlines, setidaknya LFhanya, dapat dikutip dengan garis miring terbalik di beberapa shell.
iBug
@ iBug Tidak. Dalam shell seperti sh, backslash + baris baru diperluas ke string kosong, bukan ke baris baru.
Gilles 'SO- stop being evil'
Ini jawaban yang bagus, terima kasih. Apakah ada tautan ke tempat informasi ini 'resmi' tersedia?
slashmais
1
@slashmais Informasi apa? Sintaksis bahasa shell adalah "secara resmi" tersedia dalam berbagai manual dan spesifikasi, tetapi beralih dari sana ke mencari tahu karakter mana yang perlu dikutip di mana tidak sepenuhnya mudah.
Gilles 'SANGAT berhenti menjadi jahat'
1
Saya juga menemukan ini: tecmint.com/manage-linux-filenames-with-special-characters - tidak sepadat daftar Anda, tetapi memiliki banyak contoh. (by-the-by: "Informasi apa?" bukan respons yang keren ketika topik di sini menyangkut karakter)
slashmais