Apakah ruang tidak diizinkan dalam nama file?


31

Dikatakan bahwa pada Unix dan Linux secara umum, Anda harus menghindari spasi dalam nama file file (file biasa, direktori, tautan, file perangkat, ...).

Tetapi saya melakukan itu sepanjang waktu. Untuk nama file dengan spasi di dalam,

  • Dalam Nautilus, karakter spasi ditampilkan sebagai spasi.
  • Di terminal Bash, saya gunakan \ untuk merepresentasikan spasi, atau melampirkan nama file dalam sepasang tanda kutip ganda.
  • dalam beberapa file aplikasi (Nautilus, tidak yakin apakah OS juga akan melakukannya), nama file ditulis dengan spasi diganti dengan %20.

Apakah ruang benar-benar tidak diizinkan dalam nama file?

Bagaimana Anda menggunakan atau menangani spasi dalam nama file dengan benar?


17
Itu diizinkan tapi itu benar-benar menjengkelkan. Tidak ada alasan untuk itu. Jangan lakukan itu.
Lightness Races dengan Monica

3
Anda juga dapat membuat file dengan nama -rf ~(gunakan touch -- "-rf ~"), tetapi saya tidak akan merekomendasikannya.
Ian D. Scott

5
Anda dapat melakukannya, diizinkan, seperti membuat skrip penghancuran diri yang disebut "cd" tetapi Anda tidak boleh melakukannya. File Anda sudah terlihat berbeda dalam 3 alat berbeda, bukankah itu cukup buruk?
Falco

7
Tidak semua orang berbagi pendapat bahwa itu benar-benar menjengkelkan. Dan "Tidak ada alasan untuk itu" begitu jelas salah sehingga tidak perlu disangkal. Saya menyerah dan belajar bagaimana menangani ruang dengan benar bertahun-tahun yang lalu, dan sebagian besar itu benar-benar bukan masalah besar.

2
@snailboat Spaces adalah gejala dari masalah sebenarnya yaitu kurangnya standarisasi. Filesystem Unix memungkinkan file "nama" untuk gumpalan biner hampir tidak terbatas. Satu-satunya byte ilegal adalah 0 dan 47 ( /pemisah). Menggunakan semua 254 byte tersisa membuka pintu ke semua cara "nama" eldritch yang tak terkatakan. Jelas ini gila, tetapi tidak semua orang setuju tentang apa itu "waras", dan berbagai karakter akan merusak alat yang berbeda. Persimpangan kewarasan semua orang cukup kecil .
jw013

Jawaban:


48

Spasi, dan memang setiap karakter kecuali /dan NUL, diizinkan dalam nama file. Rekomendasi untuk tidak menggunakan spasi dalam nama file berasal dari bahaya bahwa mereka mungkin disalahartikan oleh perangkat lunak yang kurang mendukungnya. Boleh dibilang, perangkat lunak semacam itu buggy. Tetapi juga bisa dibilang, bahasa pemrograman seperti shell scripting membuatnya terlalu mudah untuk menulis perangkat lunak yang rusak ketika disajikan dengan nama file dengan spasi di dalamnya, dan bug ini cenderung melewatinya karena skrip shell tidak sering diuji oleh pengembang mereka menggunakan nama file dengan spasi di mereka.

Spasi diganti dengan %20tidak sering terlihat dalam nama file. Itu sebagian besar digunakan untuk URL (web). Meskipun benar bahwa% -encoding dari URL kadang-kadang membuat jalannya menjadi nama file, seringkali secara tidak sengaja.


6
Itu "URL encoding" atau "persen encoding" en.wikipedia.org/wiki/URL_encoding Karena nama yang paling tepat mungkin "encoding URI", tetapi orang menemukan url lebih mudah untuk diucapkan daripada URI , jadi ini adalah bentuk umum dari nama yg salah. Perhatikan bahwa himpunan karakter yang dipesan dalam URI lebih besar daripada untuk * nix nama file.
goldilocks

1
@Tim Saya tidak tahu bahwa Anda dapat menentukan karakter NUL dalam argumen baris perintah apa pun di bash. Saya mencoba beberapa hal seperti mengutipnya dengan Ctrl-V dan sesuatu seperti $(echo -e \\0)tetapi tidak berhasil. Masalahnya, alasan NUL tidak dapat digunakan dalam nama file adalah bahwa itu tidak dapat digunakan dalam string C (karena itu adalah terminator string) dan semua API yang mendasari serta hampir semua string yang ditangani oleh program C menggunakan format itu . Karena bashditulis dalam C, mungkin tidak memiliki dukungan sama sekali untuk setiap string dengan NUL di dalamnya. Saya bisa saja salah, mungkin ada cara yang tidak jelas ...
Celada

1
Semacam tergantung pada konteksnya. Fungsi string umumnya tidak menghitung nol akhir (atau lebih tepatnya, nol pertama adalah akhir dari string, bahkan jika ada hal-hal setelahnya), jadi dalam arti itu memiliki panjang nol dan karena itu akan dianggap kosong.
goldilocks

3
@Celada tentu saja dapat Anda gunakan NULdan bash, yang Anda butuhkan $'\0'. Misalnya:find . -print0 | while read -d $'\0' f; do echo "$f"; done
terdon

1
@goldilocks Apakah orang benar-benar mengucapkan URL sebagai 'url', kira-kira berima dengan 'earl'?
Miles Rout

17

Ruang yang diperbolehkan dalam nama file, seperti yang Anda telah mengamati.

Jika Anda melihat entri "kebanyakan sistem file UNIX" di bagan ini di wikipedia , Anda akan melihat:

  • Kumpulan karakter 8-bit diizinkan. Kita juga dapat memasukkan ASCII 7-bit di bawah payung ini, karena ini adalah subset dari berbagai set 8-bit dan selalu diimplementasikan menggunakan 8 bit byte.

  • Satu-satunya karakter terlarang adalah /dan "null". "Null" mengacu pada byte nol, tetapi ini tidak diperbolehkan dalam data teks.

Namun , jika Anda menggunakan shell, Anda mungkin menyadari bahwa ada beberapa karakter yang akan membuat kerumitan, yang paling signifikan *, yang merupakan operator globbing POSIX.

Bergantung pada bagaimana Anda ingin mendefinisikan "kerumitan", Anda dapat menyertakan spasi putih (spasi, tab, baris baru, dll.) Di sana, karena ini menciptakan kebutuhan untuk mengutip "". Tapi ini tidak bisa dihindari, karena ruang diperbolehkan, jadi ...

Bagaimana Anda menggunakan atau menangani spasi dalam nama file dengan benar?

Dalam konteks shell / command line, bungkus nama file dalam tanda kutip tunggal atau ganda (tetapi perhatikan bahwa itu bukan WRT masalah lain yang sama ), atau lepaskan ruang dengan \, misalnya:

> foo my\ file\ with\ spaces\ in\ the\ name

1
Bagaimana Anda menentukan karakter NUL di bash? Saya ingin mengujinya dalam nama file.
Tim

1
Kamu tidak bisa "Eksekusi semantik" mengacu pada fakta bahwa dalam C (dan setiap bahasa lain yang saya ketahui), string teks diakhiri null. Shell diimplementasikan dalam C. Hal paling keren yang bisa saya pikirkan adalah touch $(echo -e "foo\00bar")- -eproses \0Nsebagai nilai oktal, tetapi masih hilang di suatu tempat, karena itu hanya membuat file bernama foobar. Tentu saja NULL tidak dapat dicetak, tapi saya jamin itu hilang dari sana karena pembatasan string C.
goldilocks

"string teks dibatalkan nol" -> Untuk menjelaskan lebih lanjut: string selalu disimpan dengan byte nol di bagian akhir, itulah sebabnya mengapa "tidak diizinkan" dalam teks: Jika Anda memasukkan satu, Anda telah secara efektif menghentikan string pada saat itu. Misalnya, foo[NULL]barakan berakhir seperti foountuk sebagian besar maksud dan tujuan. Fakta yang tidak terjadi dengan itu echo -emenunjukkan NULL telah dipangkas di suatu tempat.
goldilocks

5
Sebagian besar bahasa pemrograman memungkinkan karakter nol dalam string. Itu hanya terjadi bahwa bahasa utama yang tidak adalah C, yang dibangun oleh Unix - dan sebagian besar shell Unix tidak mengizinkan karakter null dalam string juga. Bagaimanapun, @Tim, semua antarmuka Unix menggunakan string yang diakhiri dengan nol, sehingga byte nol adalah satu hal yang tidak dapat Anda miliki dalam nama file (plus /yang merupakan pemisah direktori dan tidak dapat dikutip, sehingga bisa dalam pathname tetapi tidak dalam nama file).
Gilles 'SO- berhenti menjadi jahat'

1
... tapi [tidak apa-apa lagi]. Lagipula bukan sesuatu yang akan sering saya lakukan. Menurut saya tidak ada alasan bagi mereka untuk menggunakan data teks. Saya akan memperbaikinya, tetapi itu adalah komentar.
goldilocks

3

Alasannya sebagian besar historis - CARA kembali dalam kabut ruang waktu tidak diperbolehkan dalam nama file, sehingga ruang digunakan sebagai pemisah kata kunci / nama file. Penerjemah shell masa depan harus kompatibel dengan skrip lama, dan dengan demikian kita terjebak dengan sakit kepala yang kita miliki saat ini.

Pengembang proses yang tidak perlu berurusan dengan manusia sangat banyak dapat membuat banyak hal, lebih mudah dengan menjatuhkan ruang sama sekali. Apple melakukan ini, isi / System / Library / CoreServices / berisi sangat sedikit ruang, program dengan ruang dibuka atas nama pengguna, dan WillWookStrangeIfCamelCased. Jalur unix-only yang serupa juga menghindari spasi.

(Anekdot yang agak terkait: pada pertengahan 90-an sebuah drone Windows mengatakan "Sebutkan satu hal yang dapat Anda lakukan pada Mac yang tidak dapat saya lakukan pada Windows" -> "Gunakan 12 karakter dalam nama file." -> Diam. juga dimungkinkan dalam 12 karakter)


1
Saya dulu menggunakan V6 Unix (c. 1978). Ruang yang diizinkan kemudian. Satu tugas yang saya miliki adalah menulis sebuah program untuk mengurai sistem file (menggunakan disk langsung i / o) dan mencari file yang memiliki spasi dan backspaces dalam namanya.
wallyk

apakah mereka membuang spasi sama sekali - atau apakah nama file mengandung sedikit spasi?
mikeserv

2

Jadi ya, seperti yang dinyatakan berkali-kali di tempat lain, nama file dapat berisi hampir semua karakter. Tapi perlu dikatakan bahwa nama file adalah tidak file. Itu memang membawa bobot sebagai atribut file karena Anda biasanya memerlukan nama file untuk membuka file, tetapi nama file hanya menunjuk ke file yang sebenarnya. Ini adalah tautan, disimpan dalam direktori yang telah merekamnya, di samping nomor inode - yang merupakan perkiraan yang jauh lebih dekat dengan file aktual .

Jadi, Anda tahu, sebut saja apa yang Anda inginkan. Kernel tidak peduli - semua referensi file yang akan ditangani akan menangani nomor inode yang sebenarnya. Nama file adalah sesuatu untuk konsumsi manusia - jika Anda ingin membuatnya gila, yah, itu adalah sistem file Anda. Di sini, saya akan melakukan beberapa hal gila:

Pertama saya akan membuat 20 file, dan beri nama mereka dengan spasi, masing-masing nama file mengandung satu lebih banyak ruang daripada yang terakhir:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

Ini agak lucu. Lihat saya ls:

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

Sekarang saya akan mirror direktori ini:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

Berikut ../mirror/isinya:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

Ok, tapi mungkin Anda bertanya - tapi apa gunanya itu Bagaimana Anda bisa tahu yang mana? Bagaimana Anda bisa yakin bahwa Anda menautkan nomor inode yang tepat ke nama file yang tepat?

Baik...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

KELUARAN

heyhey
heyhey

Lihat, nomor inode yang terkandung ../mirror/"${tgt%% .*}"dan yang direferensikan dengan ./' 'merujuk ke file yang sama. Mereka menggambarkan file yang sama. Mereka menamainya, tetapi tidak lebih. Tidak ada misteri, sungguh, hanya beberapa ketidaknyamanan yang mungkin Anda buat untuk diri Anda sendiri, tetapi pada akhirnya akan sedikit berpengaruh pada operasi sistem file unix Anda pada akhirnya.

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.