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

bash에서 x 줄 이하의 디렉토리에있는 모든 파일을 삭제하는 빠르고 복잡한 방법은 무엇입니까?



답변

이해하기 쉬운 POSIX 솔루션은 다음과 같습니다.

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

마찬가지로 스테판의 대답 은 제거 echo제거됩니다 것과 때 행복합니다.


유닉스 / 리눅스에 완전히 새로운 설명을 위해 작성된 설명 :

.은 현재 디렉토리를 나타냅니다. find에서 파일과 디렉토리를 재귀 적으로 찾아서 .함께 할 수 있습니다.

-typefind기본 노드 중 하나입니다 . 재귀 적으로 발견되는 각 파일 및 디렉토리에 대해 수행되는 테스트이며 (내의 .), 라인의 나머지 1 차는 “true”인 경우에만 평가됩니다.

이 특별한 경우에, 우리 는 디렉토리 나 다른 것 (예 : 블록 장치)이 아닌 일반 파일을 다루는 경우에만 계속합니다 .


-exec(일차는 find) 외부 명령을 호출, 단지 다음 주에 진행하는 경우 성공적으로 외부 명령이 종료 ( “0”의 종료 상태). 이 명령에 {}의해 “고려 된”파일 이름으로 대체됩니다 find. 따라서 첫 번째 -exec호출은 다음 셸 명령과 동일하며 각 파일에 대해 차례로 실행됩니다.

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

Awk는 그 자체로 전체 언어이며 CSV와 같은 구분 된 텍스트 파일을 처리하도록 설계되었습니다. NR텍스트 파일의 모든 줄에 대해 Awk 조건과 명령 (작은 따옴표 사이에 포함되고 문자로 시작 )이 실행됩니다. (암시 적 반복)

Awk를 완전히 배우려면 Grymoire Tutorial을 적극 권장 하지만 위 명령에 사용 된 Awk 기능에 대해 설명하겠습니다.


-vawk는에 플래그는 우리가 awk는 명령이 우리가 설정이 경우 (파일의 각 라인.) 실행하기 전에 awk는 변수를 (한 번) 설정할 수 있습니다 x10.


NR받는 특별한 언급 된 awk 변수 ” N의 현재의 암갈색 R의 ecord입니다.” 다시 말해, 루프를 통해 특정 패스에서보고있는 행 번호입니다.

(이 점에 유의 입니다 특이한하지만, 다른 “사용 가능한 R의 ecord의 S의 설정에 의해, 개행 문자의 기본값보다 eparator을” RS. 여기에 기록 분리기와 함께 연주의 예입니다. )


일반적으로 Awk 스크립트는 동작 (중괄호 내부 )과 결합 된 조건 (중괄호 외부) 으로 구성됩니다 . 복합 조건 및 복합 동작이있을 수 있으며 기본 조건 (true) 및 기본 동작 (인쇄)이 있지만 필요합니다. 그것들을 귀찮게하지 않습니다.

여기 의 조건 은 “이것이 10 번째 줄입니까?”입니다. 이 경우, 우리는 0이 아닌 종료 상태로 종료합니다. 쉘 스크립팅에서 “명령 종료 실패”를 의미합니다.

따라서이 Awk 명령이 성공적으로 종료되는 유일한 방법 은 10 번째 줄에 도달하기 전에 파일의 끝에 도달하는 것입니다.

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


다음 -exec호출 (을 제거하면 echo)은 다음을 실행 하여 각 파일 ( find원본의 평가에서 그 정도까지)을 제거합니다 .

rm -f ./somefilename


답변

술어 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행복 경우.


답변

완전성을 위해 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) 


답변