Katakanlah saya ingin menyalin isi direktori tidak termasuk file dan folder yang namanya mengandung kata 'Musik'.
cp [exclude-matches] *Music* /target_directory
Apa yang harus dilakukan sebagai pengganti [kecocokan kecocokan] untuk mencapai ini?
bash
shell
pattern-matching
glob
pengguna4812
sumber
sumber
ls /dir/*/!(base*)
f
, kecualifoo
?The
extglob
pilihan shell memberi Anda pencocokan pola yang lebih kuat pada command line.Anda menyalakannya
shopt -s extglob
, dan mematikannya denganshopt -u extglob
.Dalam contoh Anda, pada awalnya Anda akan melakukan:
Tersedia penuh ext berakhir gumpal operator bing adalah (kutipan dari
man bash
):Jadi, misalnya, jika Anda ingin membuat daftar semua file di direktori saat ini yang bukan
.c
atau.h
file, Anda akan melakukan:Tentu saja, shell global globing berfungsi dengan baik, jadi contoh terakhir juga dapat ditulis sebagai:
sumber
.c
atau.h
file tersebut adalah direktori.D
, tetapi bukan isi dari subdirektori yang mungkin terkandung dalam direktoriD
.Bukan di bash (yang saya tahu), tetapi:
Saya tahu ini bukan apa yang Anda cari, tetapi ini akan memecahkan contoh Anda.
sumber
Jika Anda ingin menghindari biaya mem menggunakan perintah exec, saya yakin Anda bisa melakukan yang lebih baik dengan xargs. Saya pikir berikut ini adalah alternatif yang lebih efisien
sumber
Dalam bash, alternatif
shopt -s extglob
adalahGLOBIGNORE
variabel . Ini tidak benar-benar lebih baik, tetapi saya merasa lebih mudah diingat.Contoh yang mungkin diinginkan oleh pengirim aslinya:
Setelah selesai,
unset GLOBIGNORE
untuk dapatrm *techno*
di direktori sumber.sumber
Anda juga dapat menggunakan
for
loop yang cukup sederhana :sumber
-maxdepth 1
untuk non-rekursif?find
di backticks akan pecah dengan cara yang tidak menyenangkan jika ia menemukan nama file tidak trivial.Preferensi pribadi saya adalah menggunakan grep dan perintah while. Ini memungkinkan seseorang untuk menulis skrip yang kuat namun dapat dibaca memastikan bahwa Anda akhirnya melakukan apa yang Anda inginkan. Ditambah dengan menggunakan perintah echo Anda dapat melakukan dry run sebelum melakukan operasi yang sebenarnya. Sebagai contoh:
akan mencetak file yang akhirnya akan Anda salin. Jika daftar sudah benar, langkah selanjutnya adalah cukup mengganti perintah gema dengan perintah salin sebagai berikut:
sumber
bash
Anda dapat menggunakanwhile IFS='' read -r filename
, tapi kemudian baris baru masih menjadi masalah. Secara umum yang terbaik adalah tidak menggunakanls
untuk menghitung file; alat sepertifind
lebih cocok.for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; done
Sebuah trik yang saya belum melihat di sini belum yang tidak menggunakan
extglob
,find
ataugrep
untuk mengobati dua daftar file sebagai set dan "diff" dengan menggunakancomm
:comm
lebih disukai daripadadiff
karena tidak memiliki cruft tambahan.Ini mengembalikan semua elemen dari set 1
ls
,, yang tidak juga di set 2ls *Music*
,. Ini membutuhkan kedua set agar diurutkan agar berfungsi dengan benar. Tidak ada masalah untukls
dan ekspansi global, tetapi jika Anda menggunakan sesuatu sepertifind
, pastikan untuk memohonsort
.Berpotensi berguna.
sumber
comm -23 <(ls) exclude_these.list
Satu solusi untuk ini dapat ditemukan dengan find.
Temukan memiliki beberapa opsi, Anda bisa mendapatkan cukup spesifik tentang apa yang Anda sertakan dan kecualikan.
Sunting: Adam dalam komentar mencatat bahwa ini bersifat rekursif. menemukan opsi mindepth dan maxdepth dapat berguna dalam mengendalikan ini.
sumber
find -maxdepth 1 -not -name '*Music*'
/ target_directoryKarya-karya berikut mencantumkan semua
*.txt
file dalam direktori saat ini, kecuali yang dimulai dengan angka.Ini bekerja di
bash
,dash
,zsh
dan semua kerang kompatibel POSIX lainnya.Sejalan satu pola
/some/dir/*.txt
akan menyebabkanfor
loop untuk mengulangi semua file/some/dir
yang namanya berakhir dengan.txt
.Dalam baris kedua, pernyataan kasus digunakan untuk menyingkirkan file yang tidak diinginkan. -
${FILE##*/}
Ekspresi menghapus komponen dir nama terkemuka dari nama file (di sini/some/dir/
) sehingga patters dapat mencocokkan dengan hanya nama file. (Jika Anda hanya membuang nama file berdasarkan sufiks, Anda dapat mempersingkat ini menjadi$FILE
.)Pada baris ketiga, semua file yang cocok dengan
case
pola[0-9]*
) baris akan dilewati (continue
pernyataan melompat ke iterasifor
loop berikutnya). - Jika Anda ingin, Anda dapat melakukan sesuatu yang lebih menarik di sini, misalnya seperti melewatkan semua file yang tidak dimulai dengan huruf (a – z) menggunakan[!a-z]*
, atau Anda dapat menggunakan beberapa pola untuk melewati beberapa jenis nama file misalnya[0-9]*|*.bak
untuk melewati file kedua.bak
file , dan file yang tidak dimulai dengan angka.sumber
*.txt
bukan hanya*
). Diperbaiki sekarangini akan melakukannya tidak termasuk persis 'Musik'
ini dan itu untuk mengecualikan hal-hal seperti Musik? * atau *? Musik
sumber
cp
halaman manual pada MacOS memiliki-a
pilihan tetapi melakukan sesuatu yang sama sekali berbeda. Platform mana yang mendukung ini?