Saya telah menulis skrip bash kecil untuk menemukan apakah direktori bernama anaconda
atau miniconda
di pengguna saya $HOME
. Tetapi tidak menemukan miniconda2
direktori di rumah saya.
Bagaimana saya bisa memperbaikinya?
if [ -d "$HOME"/"(ana|mini)conda[0-9]?" ]; then
echo "miniconda directory is found in your $HOME"
else
echo "anaconda/miniconda is not found in your $HOME"
fi
PS: Jika saya punya [ -d "$HOME"/miniconda2 ]; then
, maka ia menemukan direktori miniconda2 jadi saya pikir kesalahan terletak pada bagian"(ana|mini)conda[0-9]?"
Saya ingin skripnya menjadi umum. Bagi saya, ini miniconda2 tetapi untuk beberapa pengguna lain mungkin anaconda2, miniconda3 dan sebagainya.
command-line
bash
scripts
Jenny
sumber
sumber
Jawaban:
Ini adalah hal yang sangat sulit dilakukan dengan baik.
Pada dasarnya,
-d
hanya akan menguji satu argumen - bahkan jika Anda bisa mencocokkan nama file menggunakan ekspresi reguler.Salah satu caranya adalah membalik masalah, dan menguji direktori untuk kecocokan regex alih-alih menguji kecocokan regex untuk direktori. Dengan kata lain, loop semua direktori dalam
$HOME
menggunakan glob shell sederhana, dan uji masing-masing terhadap regex Anda, memecahkan pertandingan, akhirnya menguji apakahBASH_REMATCH
array tidak kosong:Cara alternatif adalah dengan menggunakan glob shell diperpanjang di tempat regex, dan menangkap setiap pertandingan glob dalam array. Kemudian uji apakah array tidak kosong:
Trailing
/
memastikan bahwa hanya direktori yang cocok; yangnullglob
mencegah shell dari kembali string yang tak tertandingi dalam kasus nol pertandingan.Untuk membuat rekursif, atur
globstar
opsi shell (shopt -s globstar
) dan kemudian masing-masing: -(versi regex):
for d in "$HOME"/**/; do
(versi glob diperpanjang):
dirs=( "$HOME"/**/@(ana|mini)conda?([0-9])/ )
sumber
?([0-9])
sebagai@(|[0-9])
-?(...)
cocok dengan nol atau satu, sama dengan?
kuantifikasi regex .~/{ana,mini}conda{0..9}*/
mini
atauanaconda
dipasang di$HOME/sub-directories
? Misalnya$HOME/sub-dir1/sub-dir2/miniconda2
globstar
Memang, seperti yang telah disebutkan, ini rumit. Pendekatan saya adalah sebagai berikut:
find
dan kemampuan regex untuk menemukan direktori yang dimaksud.find
mencetakx
untuk setiap direktori yang ditemukanx
es dalam sebuah stringJadi:
Penjelasan:
find $HOME -maxdepth 1
menemukan semua yang di bawah ini$HOME
tetapi membatasi pencarian ke satu tingkat (yaitu: itu tidak muncul kembali menjadi subdirektori).-type d
membatasi pencarian hanya untukd
irectories-regextype egrep
memberitahufind
jenis ekspresi reguler yang kita hadapi. Ini diperlukan karena hal-hal seperti[0-9]?
dan(…|…)
agak spesial danfind
tidak mengenalinya secara default.-regex "$HOME/(ana|mini)conda[0-9]?"
adalah ekspresi reguler aktual yang ingin kita cari-printf 'x'
hanya mencetakx
untuk setiap hal yang memenuhi kondisi sebelumnya.sumber
-bash: -regex: command not found found one of the directories
printf
Misalnya ketika saya menjalankan skrip, itu berjalan ok tetapi tidak menemukan perintah printf ketika tidak ada yang cocok tapi saya pikir itu karena tidak ada yang mungkin dicetak?-bash: -printf: command not found no match.
-printf
bukan perintah tetapi argumen untukfind
. Itulah yang dilakukan garis miring terbalik di akhir baris sebelumnya.-quit
setelah mencetak path yang ditemukan, kecuali jika Anda ingin terus mendeteksi ambiguitas.x
sebagai gantinya:foundDir=$(find $HOME -maxdepth 1 -type d -regextype egrep -regex "$HOME/(ana|mini)conda[0-9]?" -print -quit); echo "found $foundDir"
Anda dapat mengulang daftar nama direktori yang ingin Anda uji dan bertindak jika salah satu dari mereka ada:
Solusi ini jelas tidak memungkinkan untuk kekuatan regex penuh, tetapi shell globbing dan brace ekspansi sama setidaknya dalam kasus yang Anda tunjukkan. Loop keluar segera setelah satu direktori ada dan menghapus variabel yang ditetapkan sebelumnya
a
. Padaecho
baris berikutnya , ekspansi parameter${a+not }
tidak akan berkembang jikaa
diatur (= tidak ada dir yang ditemukan) dan “tidak”.sumber
Pekerjaan yang mungkin dilakukan adalah mencari miniconda dan anaconda secara terpisah seperti yang ditunjukkan di bawah ini
Tetapi jika seseorang memiliki saran, saya ingin tahu mengapa kita tidak dapat melewati regex saat mencari direktori.
sumber
shopt -s nullglob; dirs=( "$HOME"/miniconda* "$HOME"/anaconda* ); if (( ${#dirs[@]} > 0 )); then ...
] || [
dengan-o
itu setidaknya tidak boleh pecah jika kedua direktori ditemukan karena kedua direktori gumpalan dicari dalam tes yang sama.