私は現在使用しています
watch head -n 17 *
動作しますが、17日前のすべての行も表示されます。デフォルトでは、現在の方法で表示されている各ファイルの最後の行を表示したいと思います。どうすればいいですか?
はい
たとえば、行数を減らしましょう。 7へ。だから:
サンプルファイル:
1
2
3
4
5
6
7
8
この行は:
watch head -n 7 *
出力
1
2
3
4
5
6
7
私が望む場所:
7
答え1
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
globは./*
呼び出し時に一度だけ拡張されます。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}'\'' ./*'
各反復でglobを拡張する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
ただし、これによりファイルごとに複数のコマンドが実行されるため、効率が低下します。
答え2
次の2つの例を組み合わせて、次head
のようにします。tail
$ seq 1 80 | head -n 17 | tail -n 1
17
$ seq 1 10 | head -n 17 | tail -n 1
10
したがって、実際の問題を解決するためのコマンドは次のとおりです。
watch 'for f in *; do head -n 17 -- "$f" 2>/dev/null | tail -n 1 ; done'
2>/dev/null
*は、読み取り権限のないディレクトリやファイルと一致して隠したいエラーメッセージを生成するため、この部分が必要です。
答え3
find、exec、sedを使用する別の方法
watch find . -type f -name \"*\" -exec sh -c \'\( printf '%-50s ' {} \; sed -n 17p {}\)\' \\\;