Bagaimana Linux menangani beberapa pemisah jalur berurutan (/ home //// nama pengguna ///)?

111

Saya sedang mengerjakan skrip python yang melewati lokasi file ke subproses scp. Tidak apa-apa, tapi saya berada dalam situasi di mana saya akhirnya bisa menyatukan jalur dengan nama file sehingga ada dua ' /di jalur. Saya tahu bahwa bash tidak peduli jika Anda memiliki beberapa pemisah file, tapi saya bertanya-tanya bagaimana tepatnya hal itu diperbaiki. Apakah itu bash yang strip ekstra /atau benar-benar tidak masalah?

Saya bertanya karena ini akan menyelamatkan saya beberapa baris kode untuk memeriksa tambahan /saat menggabungkan. Saya tahu ini bukan masalah besar, tapi saya juga ingin tahu. Saya memiliki skrip bash yang memiliki garis cd //usr(bukan cd /usr), yang tampaknya menyiratkan mungkin ada pentingnya menggunakan beberapa /s di jalur

Falmarri
sumber
7
Saya akan berinvestasi dalam baris kode tambahan ...
Stefan
5
Untuk berjaga-jaga kalau ada yang peduli, yang saya yakin tidak ada yang melakukannya, sebenarnya saya akhirnya menggunakan python joindan abspathperintah-perintah semacam itu.
Falmarri

Jawaban:

165

Beberapa tebasan diizinkan dan setara dengan tebasan tunggal. Dari spesifikasi Single Unix (versi 3) , definisi dasar §3.266 nama path : "Beberapa garis miring berturut-turut dianggap sama dengan satu garis miring."

Ada satu pengecualian: jika sebuah nama path dimulai dengan tepat dua garis miring, ia mungkin diperlakukan secara berbeda (ref: definisi dasar §4.11 resolusi nama path ). Linux sendiri tidak melakukan ini, meskipun beberapa aplikasi mungkin, dan sistem unix-ish lainnya melakukannya (misalnya Cygwin).

Trailing /di akhir pathname memaksa pathname untuk merujuk ke direktori. Dalam definisi dasar dalam ( POSIX 1003.1-2001 (Single Unix v3) §4.11 resolusi pathname , sebuah trailing /setara dengan sebuah trailing /.. Definisi dasar POSIX 1003.1-2008 (Single Unix v4) §4.12 menghilangkan persyaratan untuk membuatnya setara dengan /., dalam urutan untuk mengatasi direktori yang tidak ada (misalnya mkdir foo/diperlukan untuk bekerja, sedangkan mkdir foo/.tidak akan - melihat alasan perubahan).

Untuk program yang bertindak pada entri direktori, jika footautan simbolis ke direktori, maka lewat foo/adalah cara untuk membuat program bertindak di direktori alih-alih tautan simbolis.

¹ Perhatikan bahwa ini hanya berlaku untuk resolusi pathname, yaitu saat mengakses file. Manipulasi nama file dapat bekerja secara berbeda. Misalnya basenamedan dirnameabaikan garis miring garis miring.

Gilles
sumber
7
Setara dengan /.telah dihapus setelah proses diskusi selanjutnya karena ambigu. Pokoknya +1 sebagai menemukan informasi seperti ini dirangkum dengan baik adalah sulit.
hakre
17

OS tampaknya juga tidak peduli, karena baru saja mencoba program C dengan syscall langsung untuk membuka dengan // di jalan.

Anda dapat menggunakan fungsi pustaka python os.path.normpath untuk menormalkannya, yang menghemat Anda harus memindai melalui string mencari tambahan. Bahasa lain memiliki fungsi serupa.

http://docs.python.org/library/os.path.html#os.path.normpath

Ivatar
sumber
5
Waspadai komentar berikut dalam sumber normpath: Normalisasikan sebuah jalan, mis. A // B, A /./ B dan A / foo /../ B semua menjadi A / B. Harus dipahami bahwa ini dapat mengubah makna jalan jika mengandung tautan simbolis!
Bluehorn
8

Pada semua sistem Unix yang saya lihat itu sama dengan satu /, tetapi standar Unix menentukan itu

Pathname yang dimulai dengan dua garis miring berturut-turut dapat diinterpretasikan dengan cara yang ditentukan implementasi, meskipun lebih dari dua garis miring utama harus diperlakukan sebagai garis miring tunggal.

sehingga dapat ditangani secara khusus, tergantung pada sistem Anda. (Beberapa versi Unix yang lebih lama menggunakan terkemuka ganda /untuk akses sistem file jarak jauh, dan mungkin masih ada beberapa yang melakukannya.)

Fred Foo
sumber
7
Cygwin (walaupun bukan UNIX nyata) menerjemahkan //remote/...ke akses sistem file jarak jauh, mungkin untuk konsistensi dengan Windows \\remote\....
ephemient
2
Saya percaya (tetapi tidak bisa mendapatkan referensi yang bagus saat ini) bahwa API compat Windows POSIX juga akan memperlakukan //remote/...yang sama dengan \\remote\...format path UNC .
Stephen P
1
Saya pikir saya ingat bahwa nama path portabel Boost.Filesystem menangani //dengan cara khusus, karena mereka dapat menguji falseuntuk menjadi mutlak, sesuai dengan spesifikasi Unix / POSIX.
7

Gunakan os.path.joindengan Python dan Anda tidak akan mendapatkan banyak garis miring. Membangun nama file sendiri dengan menggabungkan string dianggap gaya Python yang buruk.

Neil Mayhew
sumber
Saya setuju, tetapi nama file adalah bagian dari string perintah, dan alih-alih menguraikan string perintah untuk menambahkan nama file (pada akhirnya), saya hanya ingin menambahkannya.
Falmarri
1
@ Falmarri: Anda tidak bisa hanya menambahkan nama file ke string perintah! Sebuah string perintah akan diuraikan oleh shell, jadi karakter khusus dalam nama file perlu dikutip. Jadi Anda perlu membuat nama file, lalu mengutipnya dengan benar untuk memasukkannya ke dalam string perintah.
Gilles
Ini adalah proyek yang sangat spesifik yang hanya akan saya gunakan sendiri. Saya mungkin belum cukup jelas untuk membenarkan tidak kuat tentang ini. Saya mendapatkan string jalur file ini dari kelas yang memberi saya path file yang diloloskan dengan benar dan semacamnya. Dan saya menambahkannya ke argumen baris perintah
Falmarri
1
@ Falmarri: Jadi gunakan normpath untuk membersihkan nilai baris perintah yang tidak Anda kontrol, dan kemudian gunakan bergabung untuk menyatukannya.
Neil Mayhew
Inilah yang akhirnya saya lakukan = \ Saya tidak bisa menangani kasus khusus di mana saya baru saja diberikan dengan /sangat baik.
Falmarri
3

Tidak ada perbedaan.

Beberapa garis miring diabaikan (tanpa efek), misalnya:

ls -al //usr///////bin/sed
ChristopheD
sumber
7
Ada dapat jika itu tepat dua dan di awal; Pathname yang dimulai dengan dua garis miring berturut-turut dapat ditafsirkan dengan cara yang ditentukan implementasi . Dalam praktiknya saya pikir ini benar dan mereka diabaikan
Michael Mrozek
Terima kasih Chris, saya menghargai klarifikasi ini! (sayangnya login OpenID tidak berfungsi untuk saya atau saya akan memilih Anda)
@Rob Anda tidak terdaftar, tetapi masih masuk (Anda dilacak oleh cookie Anda). Anda seharusnya dapat mendaftar sekarang untuk menghubungkan OpenID ke akun Anda, tetapi Anda harus dapat memilih dengan cara apa pun
Michael Mrozek
Terima kasih Michael tetapi "Anda harus masuk atau mendaftar untuk memilih". Saat Anda hanya menggunakan alamat dan nama email, Anda tidak memiliki hak istimewa penuh. Dan karena OpenID sedang kehabisan waktu dan saya tidak ingin membuat akun lain, saya kurang beruntung. Kesalahan saya karena malas saya kira, tetapi saya menghargai bantuannya.
0

Tentu saja Anda dapat menormalkan jalan dengan kemungkinan beberapa / (garis miring) di dalamnya dengan melewati itu tr -s

NORMALIZED=$(echo "$UNHYGIENIC" | tr -s / /)

... lalu gunakan $NORMALIZED

Namun, itu harus dilakukan. Seperti yang saya tahu kernel UNIX dengan benar harus mengabaikan pemisah jalur bersamaan --- atau secara konseptual memperlakukan mereka sebagai ... /./...

Jim Dennis
sumber
"harus" -> "tidak boleh".