나는 현재 사용하고 있습니다
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
다음 두 가지 예를 결합하고 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 {}\)\' \\\;