How can I watch the 17th (or last, if less) line in files of a folder?

With GNU awk:

watch -x gawk '
  FNR == 17 {nextfile}
  ENDFILE   {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}' ./*

Which gives an output like:

        ./file1[17] line17
  ./short-file2[05] line 5 is the last

Note that the ./* glob is expanded only once at the time watch is invoked.

Your watch head -n 17 * was an arbitrary command injection vulnerability as the expansion of that * was actually interpreted as shell code by the shell that watch invokes to interpret the concatenation of its arguments with spaces.

If there was a file called $(reboot) in the current directory, it would reboot.

With -x, we're telling watch to skip the shell and execute the command directly. Alternatively, you could do:

watch 'exec gawk '\''
  FNR == 17 {nextfile}
  ENDFILE   {if (FNR) printf "%15s[%02d] %s\n", FILENAME, FNR, $0}'\'' ./*'

For watch to run a shell which would expand that ./* glob at each iteration. watch foo bar is in effect the same as watch -x sh -c 'foo bar'. When using watch -x, you can specify which shell you want and for instance pick a more powerful one like zsh that can do recursive globbing and restrict to regular files:

watch -x zsh -c 'awk '\''...'\'' ./**/*(.)'

Without gawk, you could still do something like:

watch '
  for file in ./*; do
    [ -s "$file" ] || continue
    printf "%s: " "$file"
    head -n 17 < "$file" | tail -n 1
  done'

Giving an ouput like:

./file1: line17
./short-file2: line 5 is the last

But that would be a lot less efficient as it implies running several commands per file.


Combine head and tail like in these two examples:

$ seq 1 80 | head -n 17 | tail -n 1
17

$ seq 1 10 | head -n 17 | tail -n 1
10

So to solve your actual problem, command is:

watch 'for f in *; do head -n 17 -- "$f" 2>/dev/null | tail -n 1 ; done'

Note about the 2>/dev/null part, it is needed because * will match directories and any files you might not have permission to read, which will produce error message, which you probably want to hide.

Tags:

Bash

Watch

Head