Dengan GNU awk
:
watch -x gawk '
FNR == 17 {nextfile}
ENDFILE {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}' ./*
Yang memberikan output seperti:
./file1[17] line17
./short-file2[05] line 5 is the last
Perhatikan bahwa ./*
gumpalan diperluas hanya sekali pada saat watch
dipanggil.
Anda watch head -n 17 *
adalah kerentanan perintah injeksi sewenang-wenang sebagai perluasan yang *
benar-benar ditafsirkan sebagai kode shell oleh shell yang watch
memanggil untuk menafsirkan gabungan dari argumen dengan spasi.
Jika ada file yang dipanggil $(reboot)
di direktori saat ini, itu akan reboot.
Dengan -x
, kami meminta watch
untuk melewati shell dan menjalankan perintah secara langsung. Atau, Anda bisa melakukan:
watch 'exec gawk '\''
FNR == 17 {nextfile}
ENDFILE {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}'\'' ./*'
Untuk watch
menjalankan shell yang akan memperluas ./*
glob di setiap iterasi. watch foo bar
berlaku sama dengan watch -x sh -c 'foo bar'
. Saat menggunakan watch -x
, Anda dapat menentukan shell mana yang Anda inginkan dan misalnya memilih yang lebih kuat seperti zsh
itu dapat melakukan globbing rekursif dan membatasi ke file biasa:
watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'
Tanpa gawk
, Anda masih bisa melakukan sesuatu seperti:
watch '
for file in ./*; do
[ -s "$file" ] || continue
printf "%s: " "$file"
head -n 17 < "$file" | tail -n 1
done'
Memberikan ouput seperti:
./file1: line17
./short-file2: line 5 is the last
Tapi itu akan menjadi jauh lebih efisien karena ini berarti menjalankan beberapa perintah per file.
find . -exec
atau sth seperti ini: DGabungkan
head
dantail
sukai dalam dua contoh ini:Jadi untuk menyelesaikan masalah Anda yang sebenarnya, perintahnya adalah:
Catatan tentang
2>/dev/null
bagian ini, itu diperlukan karena * akan cocok dengan direktori dan file apa pun yang Anda mungkin tidak memiliki izin untuk membaca, yang akan menghasilkan pesan kesalahan, yang mungkin ingin Anda sembunyikan.sumber
pendekatan lain dengan find, exec dan sed
sumber