Saya terkejut baru-baru ini ketika saya melakukan sesuatu seperti
mv ./* ../somedirectory
dan menemukan bahwa file seperti .gitignore
tidak dipindahkan.
Saya melakukan sebagian besar pekerjaan saya di zsh pada OS X, dan kejutan ini menggigit saya di bash pada CentOS. Saya mencoba bash di OS X dan menemukan perilaku yang sama: *
tidak cocok dengan file dot. Ini tampaknya sangat tidak diinginkan bagi saya, tetapi ternyata itu adalah default bash. (Ini mungkin juga merupakan default zsh untuk semua yang saya ingat, tapi saya mungkin telah mengubahnya bertahun-tahun yang lalu di .zshrc saya dan lupa itu pernah bekerja secara berbeda.)
Bagaimana saya bisa mengkonfigurasi bash untuk berperilaku seperti yang saya harapkan: untuk * untuk mencocokkan semua file, dan tidak mengabaikan file dot.
Dalam hal ini sama sekali tidak jelas, inilah cara mereproduksinya
cd /tmp
mkdir {t,d}est
touch test/{.,}{1,2,3,4,5,6,7}
ls -hal test
mv test/* dest
ls -hal test # notice dot files are still there
ls -hal dest # notice only some files were mv'ed
Jawaban:
Pesta
Seperti yang sudah Anda perhatikan, bash tidak akan cocok dengan
.
di awal nama atau garis miring. Untuk mengubah yang cocok dengan titik Anda harus mengaturdotglob
opsi - man bash :Untuk mengaktifkan / mengaturnya dengan penggunaan bash
shopt
, misalnya:Untuk zsh Anda juga dapat menggunakan
dotglob
opsi tetapi tetapi Anda harus menggunakannyasetopt
untuk mengaktifkannya, misalnya:sumber
zsh
, opsi yang lebih baik adalah mengaktifkan dotglob berdasarkan per-glob:mv test/*(D) /dest
Saya menguji ini dan itu memecahkan masalah:
Keluaran:
sumber
*
adalah bola yang diperluas oleh shell. Secara default, shell tidak menyertakan file yang namanya dimulai dengan.
(disebut file atau dotfile tersembunyi) kecuali jika yang.
dimasukkan dimasukkan secara harfiah.*
atau[.]*
atau?*
atau*.*
ataudir/*
tidak akan mencakup dotfiles..*
ataudir/.*
akan.Jadi Anda bisa melakukan:
namun beberapa kerang termasuk
bash
(tetapi tidakzsh
,mksh
ataufish
) memiliki misfeature bahwa ekspansi.*
termasuk.
dan..
entri direktori khusus, yang Anda tidak ingin di sini (dan umumnya tidak pernah ingin gumpal untuk memasukkan itulah sebabnya saya menyebutnya misfeature a).Untuk alasan itu, Anda akan menemukan bahwa kadang-kadang orang menggunakan (dalam cangkang mirip Bourne):
Itu tiga gumpalan, yang pertama cocok dengan file yang tidak tersembunyi, yang kedua nama file dimulai dengan
.
diikuti oleh karakter selain.
dan yang ketiga nama file dimulai dengan..
diikuti oleh setidaknya satu karakter.Namun beberapa shell modern memiliki cara yang lebih baik
zsh
Dengan
zsh
, Anda dapat menggunakan(D)
kualifikasi glob untuk menentukan bahwa glob harus menyertakan dotfile:zsh
juga memperbaiki kesalahan lain dari shell Bourne di bahwa jika polanya tidak cocok,mv
perintah tidak dijalankan.Seperti dikatakan di atas juga tidak akan pernah termasuk
.
atau..
dalam gumpalannya, jadiakan aman. Namun jika tidak ada file yang cocok
*
atau tidak ada file yang cocok.*
dengan perintah akan dibatalkan, jadi akan lebih baik untuk menggunakan:Seperti pada beberapa shell lainnya, Anda juga dapat memaksa semua gumpalan untuk memasukkan dotfile (misalnya jika Anda mendapati dotfile ingin lebih sering dimasukkan daripada tidak) dengan:
atau:
Setelah itu, jika Anda ingin glob tertentu tidak menyertakan dotfiles, Anda dapat menulisnya:
Atau:
Pesta
Sayangnya
bash
tidak memiliki kualifikasi glob. Jadi, Anda harus mengaktifkan inklusi dotfile secara global. Dalambash
, sintaksnya adalah:(dan gunakan
[^.]*
untuk gumpalan tanpa file tersembunyi).Dengan
dotglob
,bash
tidak termasuk.
atau..
dalam gumpalan suka*
, tetapi masih untuk gumpalan suka.*
.Jika Anda mengatur
GLOBIGNORE
variabel ke sesuatu yang tidak kosong, maka secara otomatis mengaktifkandotglob
opsi dan mengecualikan.
dan..
dari.*
gumpalan tetapi tidak daridir/.*
atau.*/file
yang (!) Sehingga perlindungan cukup berguna. Anda bisa melakukannyaGLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*'
tetapi kemudian akan merusak gumpalan seperti*/.
atau./*
atau../*
.Cara lain yang lebih baik adalah menggunakan
[.]*
ataudir/[.]*
atau[.]*/file
(dengandotglob
diaktifkan) untuk memperluas dotfile kecuali.
dan..
.ikan
fish
gumpalan tidak termasuk.
juga..
. Ketika tidak ada kecocokan, tergantung pada versinya, itu akan berfungsi sepertizsh
(ataubash -o failglob
) ataubash -o nullglob
.Akan berfungsi jika ada file yang tersembunyi dan tidak tersembunyi. Jika tidak, YMMV dan dengan beberapa versi, ia dapat memanggil
mv -- /dest
jika tidak ada file sama sekali.ksh93
Tidak ada kualifikasi glob di
ksh93
keduanya. Anda dapat memasukkan dotfile dalam gumpalan dengan:Bertentangan dengan
bash
ituGLOBIGNORE
, itu dilakukan dengan benar dan juga memperbaiki masalah.*
termasuk.
dan..
.yash
yash
memilikidot-glob
opsi (set -o dot-glob
), tetapi bertentangan denganbash
, ekspansi glob (bahkan*
) termasuk.
dan..
jadi sangat tidak berguna.tcsh
Bekerja seperti dalam
bash
, yaitu*
menyertakan file titik kecuali.
dan..
tetapi.*
masih termasuk.
dan..
(dan Anda dapat menggunakan[.]*
untuk memperluas file tersembunyi kecuali.
dan..
).sumber
Cara termudah di bash untuk mencetak file titik yang cocok, abaikan
.
dan..
adalah:Untuk mengetes:
Ini mencetak semua file dengan titik-titik atau tidak, dengan pengecualian
.
dan..
.Contoh Anda juga akan berfungsi dengan benar:
Kosong file yang penting.
File sistem
.
..
masih ada tetapi ekspansi shell (menggunakan *) tidak akan memasukkannya.Dan direktori dest ination berisi semua file:
Mengapa?
Ini berfungsi karena pengaturan GLOBIGNORE memiliki efek samping ini :
shopt -s dotglob
) ke file matematika dot saat ekspansi..
dan..
diabaikan ketika GLOBIGNORE diatur dan bukan nol.Rincian di manual:
LESS=+'/The GLOBIGNORE' man bash
.Kita juga perlu mengatur variabel GLOBIGNORE untuk memuat nama yang tidak cocok dengan nama file:
garis miring (dan sesuatu yang lain hanya sebagai tindakan pencegahan ganda).
Mungkin juga berguna untuk mengatur nullglob jika diperlukan untuk menghindari mendapatkan
*
ketika tidak ada file yang cocok dengan*
.sumber
Sangat tertarik dengan pengaturan GLOBIGNORE = / + / @ user79743 ini
Dari pengalaman saya unsetting dotglob adalah bisnis yang buruk untuk hampir semua perintah Anda (cp, mv dll) TAPI yang sama berlaku pengaturan yang nullglob (terutama dengan ekspresi reguler yang kemudian perlu melarikan diri!).
Namun demikian, jika Anda perlu mengaturnya di awal program Anda tetapi mengganggu bagian-bagian tertentu di mana Anda memanggil perintah seperti cp, mv dll. Atau menggunakan ekspresi reguler lakukan saja ini:
sumber