특정 디렉토리에서 가장 오래된 디렉토리를 삭제하는 방법은 무엇입니까? [복사]

특정 디렉토리에서 가장 오래된 디렉토리를 삭제하는 방법은 무엇입니까? [복사]

중복 가능성:
가장 오래된 파일을 이동하는 쉘 스크립트?

x백업해야 하는 다른 디렉터리를 저장하는 백업 디렉터리가 있습니다 . 다른 디렉토리가 백업으로 이동되기 전에 실행되는 것이 필요합니다. 디렉토리 수에 도달했는지 확인하고 x, 도달하면 가장 오래된 디렉토리를 삭제합니다.

이는 스크립트로 수행되어야 합니다 bash.

답변1

ls다음의 출력을 구문 분석합니다.신뢰할 수 없는.

대신 을 사용하여 find디렉터리를 찾고 sort타임스탬프별로 정렬하세요. 예를 들어:

IFS= read -r -d $'\0' line < <(find . -maxdepth 1 -type d -printf '%T@ %p\0' \ 
    2>/dev/null | sort -z -n)
file="${line#* }"
# do something with $file here

이게 다 뭐하는 거야?

먼저, 이 명령은 현재 디렉터리( )의 모든 디렉터리를 find찾습니다 . 그러나 현재 디렉터리( )의 하위 디렉터리인 모든 디렉터리는 검색하지 않습니다. 그런 다음 다음을 인쇄합니다..-maxdepth 1

  • 타임스탬프
  • 공간
  • 파일의 상대 경로
  • 널 문자

타임스탬프가 중요합니다. 형식 %T@지정자는 파일의 "마지막 수정 시간"(mtime)을 나타내는 와 분수 초를 포함하여 "1970년 이후의 초 수"를 나타내는 -printf로 구분됩니다 .T@

공백은 임의의 구분 기호일 뿐입니다. 파일의 전체 경로는 나중에 참조할 수 있도록 하기 위한 것이며, NULL 문자는 파일 이름에 잘못된 문자이므로 파일 경로 끝에 도달했는지 확인할 수 있게 해주는 종결자입니다. 문서.

2>/dev/null사용자가 액세스할 수 없는 파일을 제외하도록 포함시켰지만 해당 파일이 제외되었다는 오류 메시지는 표시되지 않습니다.

이 명령의 결과 find는 현재 디렉터리의 모든 디렉터리 목록입니다. 목록은 으로 파이프되어 다음을 sort나타냅니다.

  • -zNULL을 개행 문자가 아닌 줄 종결자로 처리합니다.
  • -n숫자순으로 정렬

1970년 이후 초 수가 항상 증가하므로 타임스탬프 수가 가장 적은 파일이 필요합니다. 첫 번째 결과 sort는 가장 낮은 번호의 타임스탬프가 포함된 행이 됩니다. 남은 것은 파일 이름을 추출하는 것뿐입니다.

find, 파이프라인의 결과는 sort다음을 통과합니다.프로세스 교체to read, 표준 입력에서 파일로 읽혀집니다.

read변수를 공백으로 설정한 맥락에서 IFS이는 공백이 구분 기호로 부적절하게 해석되지 않음을 의미합니다. 이스케이프 확장을 비활성화하고 줄 끝 구분 기호를 NULL로 만들어 파이프의 출력과 일치시킨다는 것을 read알 수 있습니다 .-r-d $'\0'findsort

첫 번째 데이터 블록은 타임스탬프와 공백이 앞에 오는 가장 오래된 디렉터리 경로를 나타내며 변수로 읽혀집니다 line. 다음,매개변수 대체표현식과 함께 사용하면 #*문자열 시작 부분부터 첫 번째 공백을 포함하여 모든 문자를 null로 바꿉니다. 이렇게 하면 수정 타임스탬프가 제거되고 파일의 전체 경로만 남습니다.

이 시점에서 파일 이름은 에 저장 $file되며 rm -rf "$file".

더 쉬운 방법은 없을까요?

아니요. 더 간단한 접근 방식에는 결함이 있습니다.

and를 사용하여 ls -t파이프 하면 tail파일 이름에 줄바꿈이 포함된 파일이 중단됩니다. rm $(anything)이름에 공백이 포함된 파일은 손상될 수 있습니다 . rm "$(anything)"이름 뒤에 개행 문자가 있는 파일은 손상될 수 있습니다.

더 간단한 접근 방식으로 충분하다고 확신하는 특정 상황이 있을 수 있지만, 가능하다면 그러한 가정을 스크립트에 작성해서는 안 됩니다.

편집하다

#!/usr/bin/env bash

dir="$1"
min_dirs=3

[[ $(find "$dir" -maxdepth 1 -type d | wc -l) -ge $min_dirs ]] &&
IFS= read -r -d $'\0' line < <(find "$dir" -maxdepth 1 -printf '%T@ %p\0' 2>/dev/null | sort -z -n)
file="${line#* }"
ls -lLd "$file"

디렉터리 수를 먼저 확인하므로 문제에 대한 보다 완벽한 솔루션입니다.

답변2

다음과 같은 것을 사용할 수 있습니다.

#!/bin/sh    
keep=3

while [ `ls -1 | wc -l` -gt $keep ]; do
    oldest=`ls -c1 | head -1`
    echo "remove $oldest"
    rm -rf $oldest
done

사용하는 것이 find . -type d -maxdepth 1더 나을 수도 있지만 ls. 이는 디렉터리에 사용하는 명명 패턴에 따라 다릅니다. 자연스럽게 이름별로 올바르게 정렬된 경우 및 find또는를 사용 하여 가장 오래된/최신 디렉토리를 가져올 수 있습니다. 이 방법은 정렬을 위해 ctime 속성을 사용합니다.sortheadtaills

답변3

다음을 사용해 보세요:

rm $(ls -t1 | tail -n 1)

관련 정보