С GNU awk:
watch -x gawk '
FNR == 17 {nextfile}
ENDFILE {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}' ./*
Который дает вывод как:
./file1[17] line17
./short-file2[05] line 5 is the last
Обратите внимание, что ./*глобус расширяется только один раз в тот момент, когда watchвызывается.
Ваша watch head -n 17 *уязвимость была связана с произвольным введением команд, поскольку расширение, которое *фактически интерпретировалось оболочкой как код оболочки, watchвызывает интерпретацию объединения аргументов с пробелами.
Если $(reboot)в текущем каталоге был вызван файл , он перезагрузился бы.
С помощью -xмы говорим watchпропустить оболочку и выполнить команду напрямую. В качестве альтернативы вы можете сделать:
watch 'exec gawk '\''
FNR == 17 {nextfile}
ENDFILE {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}'\'' ./*'
Для watchзапуска оболочки, которая будет расширять этот ./*шар на каждой итерации. watch foo barв действительности так же, как watch -x sh -c 'foo bar'. При использовании watch -xвы можете указать, какая оболочка вам нужна, и, например, выбрать более мощную, например zsh, такую, которая может выполнять рекурсивное сглаживание и ограничиваться обычными файлами:
watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'
Без gawk, вы все еще можете сделать что-то вроде:
watch '
for file in ./*; do
[ -s "$file" ] || continue
printf "%s: " "$file"
head -n 17 < "$file" | tail -n 1
done'
Давать выходной как:
./file1: line17
./short-file2: line 5 is the last
Но это было бы намного менее эффективно, так как подразумевает выполнение нескольких команд на файл.
find . -execнапример, так: D