head 명령에서 오류가 발생했습니다. 디렉터리에는 두 개의 48바이트 파일이 있으며 디렉터리 경로와 함께 두 번 인쇄되는 대신 한 번만 인쇄됩니다. head 명령이 처음 두 파일을 고려하지 않는 이유는 무엇입니까 head -n 2
? 다른 방법이 있나요?
내 코드:
find "$dir" -type f -printf '%s %p\n' | sort -n -r | head -n 2|
{
read -r file dir
printf "size: %d\n\t%s\n" "$file" "$dir"
}
내 출력 오류:
size: 48
testdir/file7.txt
testdir 디렉토리에는 동일한 크기 48의 두 파일이 포함되어 있지만 디렉토리 경로와 함께 두 번이 아닌 한 번만 발생합니다.
내가 원하는 출력:
size: 48
testdir/file7.txt
testdir/file1.txt
답변1
head -n 2
; 오류가 없습니다. |
코드를 제거하고 따라가면 이를 확인할 수 있습니다.
문제는 중괄호 사이의 코드가 한 번만 실행된다는 것입니다. 이는 루프가 아닙니다. read
한 줄의 입력에서만 데이터를 읽습니다 . 따라서 여러 파일의 데이터를 인쇄하려면 일종의 루프를 수행해야 합니다.
루프를 사용 while
하거나 awk의 내장 루프를 활용하여 데이터를 읽고 인쇄할 수 있습니다. 예를 들어, 다음 awk 명령은 현재 파일의 크기가 이전 파일의 크기와 다른 경우 크기 정보만 인쇄합니다.
awk 'BEGIN{size=-1}; {if($1!=size){size=$1; printf "size: %d\n", size}; printf "\t%s\n", $2}'
우리는하지 않습니다진짜자동으로 빈 문자열로 초기화되므로 명시적인 초기화가 필요 size
하지만 IMHO 이러한 사항을 명확히 하는 것이 좋습니다.
awk 명령은 다음을 대체합니다.
{
read -r file dir
printf "size: %d\n\t%s\n" "$file" "$dir"
}
코드 섹션. 즉, 다음을 사용할 수 있습니다.
find "$dir" -type f -printf '%s %p\n' |
sort -n -r | head -n 2 |
awk 'BEGIN{size=-1};
{if($1!=size){size=$1; printf "size: %d\n", size};
printf "\t%s\n", $2}'
한 줄에 모두 넣을 수도 있고 여러 줄로 나눌 수도 있습니다. awk 프로그램을 자체 파일에 넣는 것도 가능하지만 그렇게 작은 프로그램에는 필요하지 않습니다.
-n
원하는 크기를 선택할 수 head
있으며 awk 프로그램은 예상대로 실행됩니다. 또한 awk는매우read
빠르다 - 및 를 사용하는 것보다 더 효율적입니다 printf
.
FWIW, 간단한 텍스트 처리를 위한 awk 코드는 종종 동등한 Python 코드보다 훨씬 빠르므로 많은 사람들이 awk를 쓸모없다고 생각하지만 여전히 꽤 인기가 있습니다.
데이터 인쇄오직디렉터리에서 가장 큰 파일은 다음과 같습니다.
find . -type f -printf '%s %p\n' |
sort -nr |
awk 'NR==1{size=$1;printf "size: %d\n", size};
$1!=size{exit};
{printf "\t%s\n", $2}'
이는 레코드 수가 1인 경우에만 NR==1
다음 블록(in )이 실행된다는 것을 의미합니다. 레코드는 단 하나의 행입니다. {}
따라서 (이전 명령 덕분에) 가장 큰 파일인 첫 번째 파일의 크기를 가져와 변수 sort
에 저장 하고 크기를 인쇄합니다.size
$1!=size{exit}
첫 번째 필드의 데이터가 변수에 저장한 데이터와 일치하지 않는 줄을 읽는 즉시 프로그램을 종료한다는 의미입니다 size
.
마지막 블록은 {printf "\t%s\n", $2}
각 파일의 경로 이름을 인쇄합니다.
find
이 명령으로 찾은 가장 큰 파일과 가장 작은 파일을 인쇄하는 방법에는 여러 가지가 있습니다 . 한 가지 방법은 모든 데이터를 awk로 읽어서 배열에 저장하고 배열을 정렬한 다음 가장 큰 파일과 가장 작은 크기의 파일에 대한 데이터를 인쇄하는 것입니다. 하지만 여기서는 더 간단한 전략을 채택하고 기존 코드를 재활용하겠습니다. 이를 보다 효율적으로 수행하기 위해 awk 프로그램을 파일에 넣었습니다. 이 파일을 명령 경로의 디렉터리에 저장하고 실행 권한을 부여합니다.
field1match.awk
#!/usr/bin/awk -f
# print only the records whose 1st field matches that of the 1st record
# Written by PM 2Ring 2015.05.21
NR==1{size=$1; printf "size: %d\n", size}
$1!=size{exit}
{printf "\t%s\n", $2}
tee
다음은 출력을 복사 find
한 다음 정렬하고 프로세스 대체를 사용하여 인쇄하는 명령줄입니다 .
find "$dir" -type f -printf '%s %p\n' |
tee > >(sort -n | field1match.awk) >(sort -rn | field1match.awk)