bash에서 x 줄 아래 디렉토리의 모든 파일을 삭제하는 빠르고 복잡하지 않은 방법이 있습니까?
답변1
이것은 POSIX 솔루션이며 이해하기 매우 쉽습니다.
find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;
에서와 같이스티븐의 대답, 삭제에 echo
만족하면 삭제됩니다.
Unix/Linux 초보자를 위해 작성된 설명:
점은 .
현재 디렉터리를 나타냅니다. find
파일과 디렉터리는 에서 반복적으로 발견되며 .
이에 대해 작업을 수행할 수 있습니다.
-type
find
그 중 하나야예비 선거;이것은 반복적으로(포함) 발견된 모든 파일 및 디렉터리에 대해 실행되는 테스트이며 .
, 해당 줄의 나머지 기본 항목은 결과가 "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)