x줄 미만의 파일을 삭제하는 빠른 방법

x줄 미만의 파일을 삭제하는 빠른 방법

bash에서 x 줄 아래 디렉토리의 모든 파일을 삭제하는 빠르고 복잡하지 않은 방법이 있습니까?

답변1

이것은 POSIX 솔루션이며 이해하기 매우 쉽습니다.

find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;

에서와 같이스티븐의 대답, 삭제에 echo만족하면 삭제됩니다.


Unix/Linux 초보자를 위해 작성된 설명:

점은 .현재 디렉터리를 나타냅니다. find파일과 디렉터리는 에서 반복적으로 발견되며 .이에 대해 작업을 수행할 수 있습니다.

-typefind그 중 하나야예비 선거;이것은 반복적으로(포함) 발견된 모든 파일 및 디렉터리에 대해 실행되는 테스트이며 ., 해당 줄의 나머지 기본 항목은 결과가 "true"인 경우에만 평가됩니다.

이 특별한 경우에는 우리가 다음을 처리하는 경우에만일반 파일, 디렉토리나 다른 것(예: 블록 장치)이 아닙니다.


마스터 -exec노드는 find외부 명령을 호출하고 외부 명령이 성공적으로 종료된 경우에만 다음 마스터 노드로 진행합니다(종료 상태는 '0'). {}명령에 의해 "고려된" 파일 이름으로 대체되었습니다 find. 따라서 첫 번째 -exec호출은 각 파일에 대해 차례로 실행되는 다음 셸 명령과 동일합니다.

awk -v x=10 'NR==x{exit 1}' ./somefilename

awk는 그 자체로 완전한 언어입니다.CSV와 같이 구분된 텍스트 파일을 처리하도록 설계되었습니다. Awk 조건 및 명령(작은따옴표로 묶이고 문자로 시작 NR)은 텍스트 파일의 각 줄에서 실행됩니다. (암시적 루프.)

Awk를 완전히 배우려면 강력히 추천합니다희미한 빛 튜토리얼, 그러나 위 명령에 사용된 Awk 기능에 대해 설명하겠습니다.


Awk 플래그를 -v사용하면 Awk 명령을 실행하기 전에(파일의 각 줄에 대해) Awk 변수를 (한 번) 설정할 수 있습니다. 이 경우에는 x로 설정했습니다 10.


NR"를 참조하는 특별한 Awk 변수입니다.질소현재 수량오른쪽에코. ” 즉, 루프의 특정 패스에서 우리가 보고 있는 줄 번호입니다.

(참고하세요.특이하지만 다른 "를 사용하는 것이 가능합니다.오른쪽에코코드에스에 의해 설정된 기본 개행 문자보다 "eparator"가 RS. 다음은 레코드 구분 기호를 사용한 재생의 예입니다.)


awk 스크립트에는 일반적으로 다음이 포함됩니다.상황(중괄호 외부) 결합행동(중괄호 안에.) 복합 조건과 복합 연산이 있을 수 있고 기본 조건(true)과 기본 동작(print)이 있지만 걱정할 필요가 없습니다.

이것상황"이 줄이 10입니까?"입니다. 그렇다면 0이 아닌 종료 상태로 종료합니다. 이는 쉘 스크립트에서 "명령 종료 실패"를 의미합니다.

그러므로Awk 명령은 종료하는 유일한 방법입니다성공적으로10행에 도달하기 전에 파일의 끝에 도달했는지 여부를 나타냅니다.

따라서 awk 스크립트가 성공적으로 종료되면 10줄 미만의 파일이 있다는 의미입니다.


다음 -exec호출(삭제된 경우 )은 다음을 실행하여 echo모든 파일(기본 평가의 이 시점까지)을 삭제합니다 .find

rm -f ./somefilename

답변2

find조건자를 지원하는 구현을 가정합니다 -readable( find지원하지 않는 경우 제거하면 파일을 읽을 수 없다는 오류 메시지가 표시되거나 로 대체됩니다 -exec test -r {} \;).

x=10 find . -type f -readable -exec sh -c '
  for file do
    lines=$(wc -l < "$file") && [ "$((lines))" -lt "$x" ] && echo rm -f "$file"
  done' sh {} +

echo만족스러우면 삭제하세요 .

이는 중요하기 때문에 특별히 효율적이지는 않습니다.모두x행이 있으며 첫 번째 파일 에서만 중지하면 되며 각 파일에 대해 하나 wc(아마도 하나 rm)의 명령을 실행합니다.

GNU를 사용하면 awk다음과 같이 효율성을 향상시킬 수 있습니다.

x=10
find . -type f -readable -exec awk -v x="$x" -v ORS='\0' '
  FNR == x {nextfile}
  ENDFILE {if (FNR < x) print FILENAME}' {} +|
  xargs -r0 echo rm -f

(다시 한번 말하지만 echo만족스러우면 삭제하세요).

다음과 동일 perl:

x=10 find . -type f -readable -exec perl -Tlne '
  if ($. == $ENV{x}) {close ARGV}
  elsif (eof) {print $ARGV; close ARGV}' {} +

print마음에 들면 바꾸세요 unlink.

답변3

완전성을 위해 AWK 외에도 GNU sed를 사용하여 동일한 결과를 얻을 수도 있습니다.

find . -type f -exec sed 11q1 '{}' ';' -exec echo rm -f '{}' ';'

그 결과 명령줄이 더 깔끔해졌습니다.

설명하다

11 - is the address, i.e. "the eleventh line"
q - is for _q_uit (abort the execution)
1 - is the exit code parameter for q (GNU sed extension) 

관련 정보