Saya mencoba menulis if
pernyataan untuk menguji apakah ada file yang cocok dengan pola tertentu. Jika ada file teks dalam direktori itu harus menjalankan skrip yang diberikan.
Kode saya saat ini:
if [ -f /*.txt ]; then ./script fi
Tolong beri beberapa ide; Saya hanya ingin menjalankan skrip jika ada .txt
di direktori.
shell-script
files
wildcards
test
pengguna40952
sumber
sumber
/
? Juga, Anda kehilangan titik koma sebelumnyafi
.find
seperti yang dijelaskan di sini di stackoverflow .Jawaban:
akan mengembalikan true hanya jika ada satu (dan hanya satu) file tidak tersembunyi
/
yang namanya berakhir.txt
dan jika file itu adalah file biasa atau symlink ke file biasa.Itu karena wildcard diperluas oleh shell sebelum diteruskan ke perintah (di sini
[
).Jadi jika ada
/a.txt
dan/b.txt
,[
akan diteruskan 5 argumen:[
,-f
,/a.txt
,/b.txt
dan]
.[
kemudian akan mengeluh karena-f
diberi terlalu banyak argumen.Jika Anda ingin memeriksa apakah
*.txt
polanya meluas ke setidaknya satu file yang tidak disembunyikan (biasa atau tidak):shopt -s nullglob
adalahbash
spesifik, tapi kerang sepertiksh93
,zsh
,yash
,tcsh
memiliki pernyataan setara.Perhatikan bahwa ia menemukan file-file itu dengan membaca konten direktori, itu tidak mencoba dan mengakses file-file itu sama sekali yang membuatnya lebih efisien daripada solusi yang memanggil perintah seperti
ls
ataustat
pada daftar file yang dihitung oleh shell.sh
Setara standar akan menjadi:Masalahnya adalah bahwa dengan cangkang Bourne atau POSIX, jika suatu pola tidak cocok, itu mengembang sendiri. Jadi jika
*.txt
diperluas*.txt
, Anda tidak tahu apakah itu karena tidak ada.txt
file di direktori atau karena ada satu file yang dipanggil*.txt
. Menggunakan[*].txt *.txt
memungkinkan untuk membedakan keduanya.sumber
[ -f /*.txt ]
cukup cepat dibandingkan dengancompgen
.[ -f /*.txt ]
akan salah, tetapi dalam pengujian saya pada direktori yang berisi3425
file,94
di antaranya adalah file txt yang tidak tersembunyi,compgen -G "*.txt" > /dev/null 2>&1
nampak secepatset -- *.txt; [ "$#" -gt 0 ]
(20,5 detik untuk keduanya ketika diulang 10.000 kali dalam kasus saya).Anda selalu dapat menggunakan
find
:Penjelasan:
find .
: cari direktori saat ini-maxdepth 1
: jangan mencari subdirektori-type f
: hanya mencari file biasaname "*.txt"
: cari file yang diakhiri dengan.txt
2>/dev/null
: redirect pesan kesalahan ke/dev/null
| grep -q .
: grep untuk karakter apa pun, akan mengembalikan false jika tidak ada karakter yang ditemukan.&& ./script
: Jalankan./script
hanya jika perintah sebelumnya berhasil (&&
)sumber
find
hanya mengembalikan false jika mengalami kesulitan mencari file, tidak jika tidak menemukan file apa pun. Anda ingin menyalurkan outputgrep -q .
untuk memeriksa apakah ia menemukan sesuatu.chmod a-x .
.Solusi yang mungkin juga Bash builtin
compgen
. Perintah itu mengembalikan semua kemungkinan kecocokan untuk pola globbing dan memiliki kode keluar yang menunjukkan apakah ada file yang cocok.Saya menemukan pertanyaan ini sambil mencari solusi yang lebih cepat.
sumber
LC_ALL=C compgen -G "*.txt" > /dev/null
.Berikut ini satu liner untuk melakukannya:
file ada
file tidak ada
Pendekatan ini memanfaatkan
||
dan&&
operator di bash. Ini adalah operator "atau" dan "dan".Jadi jika perintah stat mengembalikan
$?
sama dengan 0 maka yang pertamaecho
dipanggil, jika mengembalikan 1, maka yang keduaecho
disebut.kembalikan hasil dari stat
Pertanyaan ini banyak dibahas pada stackoverflow:
sumber
stat
bilals -d
bisa melakukan hal yang sama?ls -d
daftar direktori? Sepertinya tidak berfungsi ketika saya baru saja mencoba daftar direktori dengan file di dalamnyals -d *.pl
misalnya.&&
olehls *.txt
dan itu akan berfungsi juga. Pastikan Anda mengirim stdout dan stderr ke/dev/null
seperti yang disarankan oleh @slm.ls *.txt
dan tidak ada file hadir dalam direktori ini akan kembali$? = 2
, yang masih akan bekerja dengan jika kemudian, tapi ini adalah salah satu alasan saya untuk memilihstat
lebihls
. Saya ingin 0 untuk sukses, dan 1 untuk kegagalan.ls -d
adalah untuk mendaftar direktori alih-alih isinya. Jadils -d
lakukan sajalstat
pada file, seperti halnya GNUstat
. Perintah status keluar non-nol yang dikembalikan pada kegagalan adalah spesifik sistem, tidak masuk akal untuk membuat asumsi pada mereka.Seperti yang ditunjukkan Chazelas, skrip Anda akan gagal jika ekspansi wildcard cocok dengan lebih dari satu file.
Namun, ada trik yang saya gunakan ( bahkan saya tidak terlalu menyukainya ) untuk berkeliling:
Bagaimana itu bekerja?
Ekspansi wildcard akan cocok dengan array nama file, kami mendapatkan yang pertama jika ada beberapa, jika tidak, nol jika tidak ada kecocokan.
sumber
.txt
file lain yang bertipe biasa . Coba misalnya setelahmkdir a.txt; mkfifo b.txt; echo regular > c.txt
.Sederhana seperti:
wc -l
menghitung garis dalam wildcard yang diperluas.sumber
ls
output dan hampir tidak pernah memeriksa$?
secara langsung karenaif
sudah melakukan itu. Juga, menggunakanwc
untuk melihat apakah sesuatu terjadi juga salah arah.Saya suka solusi array sebelumnya, tapi itu bisa menjadi boros dengan banyak file - shell akan menggunakan banyak memori untuk membangun array, dan hanya elemen pertama yang akan diuji.
Berikut adalah struktur alternatif yang saya uji kemarin:
$ cd /etc; if [[ $(echo * | grep passwd) ]];then echo yes;else echo no;fi yes $ cd /etc; if [[ $(echo * | grep password) ]];then echo yes;else echo no;fi no
Nilai keluar dari grep tampaknya menentukan jalur melalui struktur kontrol. Ini juga menguji dengan ekspresi reguler daripada pola shell. Beberapa sistem saya memiliki perintah "pcregrep" yang memungkinkan pertandingan regex yang jauh lebih canggih.
(Saya memang mengedit jawaban ini untuk menghapus "ls" dalam substitusi perintah setelah membaca kritik di atas karena menguraikannya.)
sumber
jika Anda ingin menggunakan klausa if, evaluasi penghitungan:
sumber