bash에서 x 줄 이하의 디렉토리에있는 모든 파일을 삭제하는 빠르고 복잡한 방법은 무엇입니까?
답변
이해하기 쉬운 POSIX 솔루션은 다음과 같습니다.
find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;
마찬가지로 스테판의 대답 은 제거 echo
제거됩니다 것과 때 행복합니다.
유닉스 / 리눅스에 완전히 새로운 설명을 위해 작성된 설명 :
점 .
은 현재 디렉토리를 나타냅니다. find
에서 파일과 디렉토리를 재귀 적으로 찾아서 .
함께 할 수 있습니다.
-type
find
의 기본 노드 중 하나입니다 . 재귀 적으로 발견되는 각 파일 및 디렉토리에 대해 수행되는 테스트이며 (내의 .
), 라인의 나머지 1 차는 “true”인 경우에만 평가됩니다.
이 특별한 경우에, 우리 는 디렉토리 나 다른 것 (예 : 블록 장치)이 아닌 일반 파일을 다루는 경우에만 계속합니다 .
-exec
(일차는 find
) 외부 명령을 호출, 단지 다음 주에 진행하는 경우 성공적으로 외부 명령이 종료 ( “0”의 종료 상태). 이 명령에 {}
의해 “고려 된”파일 이름으로 대체됩니다 find
. 따라서 첫 번째 -exec
호출은 다음 셸 명령과 동일하며 각 파일에 대해 차례로 실행됩니다.
awk -v x=10 'NR==x{exit 1}' ./somefilename
Awk는 그 자체로 전체 언어이며 CSV와 같은 구분 된 텍스트 파일을 처리하도록 설계되었습니다. NR
텍스트 파일의 모든 줄에 대해 Awk 조건과 명령 (작은 따옴표 사이에 포함되고 문자로 시작 )이 실행됩니다. (암시 적 반복)
Awk를 완전히 배우려면 Grymoire Tutorial을 적극 권장 하지만 위 명령에 사용 된 Awk 기능에 대해 설명하겠습니다.
-v
awk는에 플래그는 우리가 awk는 명령이 우리가 설정이 경우 (파일의 각 라인.) 실행하기 전에 awk는 변수를 (한 번) 설정할 수 있습니다 x
에 10
.
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)