Apa artinya. ?? * artinya dalam perintah shell?

22

The berikut perintah akan tarsemua "dot" file dan folder:

tar -zcvf dotfiles.tar.gz .??*

Saya terbiasa dengan ekspresi reguler , tetapi saya tidak mengerti bagaimana menafsirkannya .??*. Saya mengeksekusi ls .??*dan tree .??*dan melihat file-file yang terdaftar. Mengapa ungkapan reguler ini mencakup semua file dalam folder yang dimulai dengan .misalnya?

SabreWolfy
sumber

Jawaban:

32

Glob bukan ekspresi reguler. Secara umum, shell akan mencoba menginterpretasikan apa pun yang Anda ketikkan pada baris perintah yang tidak Anda kutip sebagai glob. Kerang tidak diperlukan untuk mendukung ekspresi reguler sama sekali (walaupun pada kenyataannya banyak pelamun yang lebih modern melakukannya, misalnya =~operator pencocokan regex dalam bash [[konstruksi).

Ini .??*adalah bola. Ini cocok dengan nama file apa pun yang dimulai dengan titik literal ., diikuti oleh dua karakter (tidak harus sama) ??, diikuti oleh persamaan ekspresi reguler [^/]*, yaitu 0 atau lebih karakter yang tidak /.

Untuk detail lengkap ekspansi shell pathname (nama lengkap untuk "globbing"), lihat spesifikasi POSIX .

jw013
sumber
10
Poin tambahan: ini adalah upaya untuk menulis sebuah bola dunia yang cocok dengan semua berkas berkas dalam direktori kecuali entri khusus .dan .., yang orang biasanya tidak ingin melakukan apa pun dengan. Itu tidak benar; itu tidak mengambil apa pun yang bernama ' .X' di mana X adalah beberapa karakter selain titik. Saya tidak berpikir itu mungkin untuk menulis satu bola dunia yang cocok dengan setiap dotfile kecuali .dan .., tetapi Anda bisa melakukannya dengan dua: tar zcvf dotfiles.tar.gz .[!.] .??*misalnya.
zwol
@Zack: Terima kasih atas klarifikasi. Saya mengirim komentar tentang itu, tetapi kemudian menghapusnya. ls .?mengembalikan sama dengan ls .., yang berarti tidak ada entri lain di folder yang cocok dengan polanya .?. Saya akan lakukan .[^.]untuk semua .?file selain ...
SabreWolfy
2
@ SabreWolfy Jika Anda membaca spec POSIX dengan hati-hati, itu sebenarnya perbedaan penting antara gumpalan dan regex: dalam ekspresi braket, [^abc]dalam sintaks regex berarti sama dengan [!abc]di sintaks glob (yaitu ^diganti dengan !untuk gumpalan). Menggunakan [^abc]sintaks gaya dalam glob tidak terlalu portabel karena POSIX tidak menentukan apa artinya, sehingga beberapa shell menafsirkannya menggunakan semantik seperti regex sementara yang lain memperlakukannya ^hanya sebagai karakter literal.
jw013
1
@ jw013: Terima kasih untuk detailnya. Saya harus ingat glob itu! = Regexp :)
SabreWolfy
1
Hanya terpikir oleh saya bahwa .[!.]mungkin dibiarkan sebagai literal pada tarbaris perintah dalam kasus umum di mana tidak ada file yang cocok dengan pola itu. Beberapa shell memungkinkan Anda mengontrol perilaku itu, misalnya dengan bash, shopt -s nullglobakan membuatnya menghilang dari baris perintah jika tidak cocok dengan apa pun, tetapi itu bukan fitur universal.
zwol
8

The .??*wildcard ( bukan ekspresi reguler, meskipun tampak seperti itu) diterjemahkan ke dalam nama file yang dimulai dengan periode ( .), diikuti oleh dua karakter tunggal ( ??), dan kemudian sejumlah (nol atau lebih) dari karakter lain ( *).

Mungkin halaman tentang Wildcard di Nama File ini akan membantu.

Levon
sumber
-1

Untuk menambah jawaban lain, satu ?akan menerjemahkan ke nama file karakter tunggal dan ??akan cocok dengan nama file yang hanya memiliki dua karakter dan seterusnya.

[root@mercy testdir_2]# ls
ion  it  r
[root@mercy  testdir_2]# ls ?
r
[root@mercy  testdir_2]# ls ??
it
[root@mercy 1 testdir_2]# ls ???
ion
[root@mercy  testdir_2]#
Sree
sumber
Downvoter, bisakah Anda berkomentar? Akan senang dikoreksi, jika saya salah.
Sree
Jawaban Anda tidak menjawab pertanyaan sepenuhnya.
SabreWolfy