Con GNU awk:
watch -x gawk '
FNR == 17 {nextfile}
ENDFILE {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}' ./*
Che dà un output come:
./file1[17] line17
./short-file2[05] line 5 is the last
Si noti che il ./*glob viene espanso solo una volta al momento watchviene richiamato.
La tua watch head -n 17 *era una vulnerabilità di iniezione di comando arbitraria in quanto l'espansione di quella *era in realtà interpretata come codice shell dalla shell che watchinvoca per interpretare la concatenazione dei suoi argomenti con spazi.
Se fosse presente un file chiamato $(reboot)nella directory corrente, verrà riavviato.
Con -x, stiamo dicendo watchdi saltare la shell ed eseguire direttamente il comando. In alternativa, potresti fare:
watch 'exec gawk '\''
FNR == 17 {nextfile}
ENDFILE {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}'\'' ./*'
Per watcheseguire una shell che espanderebbe quel ./*glob ad ogni iterazione. watch foo barè in effetti lo stesso di watch -x sh -c 'foo bar'. Quando si utilizza watch -x, è possibile specificare quale shell si desidera e, ad esempio, sceglierne una più potente come zshquella può fare globbing ricorsivo e limitarsi ai file regolari:
watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'
Senza gawk, potresti ancora fare qualcosa del tipo:
watch '
for file in ./*; do
[ -s "$file" ] || continue
printf "%s: " "$file"
head -n 17 < "$file" | tail -n 1
done'
Dare un'uscita come:
./file1: line17
./short-file2: line 5 is the last
Ma sarebbe molto meno efficiente in quanto implica l'esecuzione di più comandi per file.
find . -execo sth in questo modo: D