가장 오래된 파일을 제거


9

디렉토리에서 오래된 파일을 삭제하고 3 개의 최신 파일 만 남겨 두려고합니다.

cd /home/user1/test

while [ `ls -lAR | grep ^- | wc -l` < 3 ] ; do

    rm `ls -t1 /home/user/test | tail -1`
    echo " - - - "

done

조건문에 문제가 있습니다.

답변:


9

파일을 반복 하려면ls *를 사용하지 마십시오 . tl; dr 잘못된 파일 또는 모든 파일을 삭제하는 상황이 많이 있습니다.

불행히도 이것은 Bash에서 제대로하기가 까다로운 일입니다. 에서 이상 작동 답있다 중복 된 질문은 내 나이도 당신이 작은 수정을 사용할 수있는 : find_date_sorted

counter=0
while IFS= read -r -d '' -u 9
do
    let ++counter
    if [[ counter -gt 3 ]]
    then
        path="${REPLY#* }" # Remove the modification time
        echo -e "$path" # Test
        # rm -v -- "$path" # Uncomment when you're sure it works
    fi
done 9< <(find . -mindepth 1 -type f -printf '%TY-%Tm-%TdT%TH:%TM:%TS %p\0' | sort -rz) # Find and sort by date, newest first

* 공격자 없음-나는 또한 ls전에 사용 했다. 그러나 실제로 안전하지 않습니다.

편집 : 단위 테스트의 새로운 기능find_date_sorted .


나는 ls를 파싱하지 않는 것에 대해 두 번째 부분. 또한 스크립트는 깔끔하지만 하나의 라이너로도 가능하다고 생각합니다.
rahmu

글쎄, 당신은 항상 컴팩트 배쉬 한 라이너로 코드를하지만, 문제는 :) 읽을 수 있습니다 여부 수 있습니다
l0b0

2
@ Peter.O의 아이디어를 무자비하게 훔칠 수 있다면 ((++counter>3))테스트 해보 십시오. 간결합니다. oneliners의 경우 : 간결함을 염두에두고 코드를 함수로 감싼다면 걱정하지 마십시오.
Sorpigal

@Sorpigal 깔끔한 바로 가기
l0b0

5

zsh glob을 사용하여 3 개의 최신 파일을 제외한 모든 파일을 삭제하려면 Om(자본 O)를 사용 하여 파일을 가장 오래된 것부터 가장 오래된 것으로 정렬하고 아래 첨자를 사용하여 원하는 파일을 가져올 수 있습니다.

rm ./*(Om[1,-4])
#    | ||||  ` stop at the 4th to the last file (leaving out the 3 newest)
#    | |||` start with first file (oldest in this case)
#    | ||` subscript to pick one or a range of files
#    | |` look at modified time
#    | ` sort in descending order
#    ` start by looking at all files

다른 예 :

# delete oldest file (both do the same thing)
rm ./*(Om[1])
rm ./*(om[-1])

# delete oldest two files
rm ./*(Om[1,2])

# delete everything but the oldest file
rm ./*(om[1,-2])

5

지금까지 가장 쉬운 방법은 zsh와 해당 glob 한정자 를 사용하는 것입니다 . Om나이를 줄이면서 (즉 가장 오래된 것부터) 정렬 [1,3]하고 처음 세 개의 일치 항목 만 유지하는 것입니다.

rm ./*(Om[1,3])

더 많은 예제 는 zsh에서 글로브를 필터링하는 방법을 참조하십시오 .

l0b0의 조언에 유의 하십시오 : 쉘 특수 문자가 포함 된 파일 이름이 있으면 코드가 끔찍하게 중단됩니다.


Woa woa woa 기차를 타야, 이것이 실제로 한 줄로 완벽한 솔루션입니까?
MetaGuru

2
@Ryan 그것은 당신을 위해 zsh입니다.
Gilles 'SO- 악마 그만해'

1

다음 함수를 사용하여 디렉토리에서 최신 파일을 가져올 수 있습니다.

newest_in() 
{ 
    local newest=$1

    for f;do [[ $f -nt $newest ]] && newest="$f"; done;

    printf '%s\n' "$newest"
}

각 반복 후에 최신 파일을 제외하여 다른 파일 세트를 제공하십시오.

팁 : "$ {files [@]}"라는 배열에 초기 파일 세트를 보유한 경우 발견 된 최신 파일의 색인을 unset 'files[index]'다음 반복 전에 저장하십시오 .

용법: newest_in [set of files/directories]

샘플 출력 :

[rany$] newest_in ./*
foo.txt
[rany$]

-1

첫째, -R옵션은 재귀에 대한 것이며, 아마도 원하는 것이 아닐 수도 있습니다. 모든 하위 디렉토리에서도 검색됩니다. 둘째, <연산자 (리디렉션으로 표시되지 않은 경우)는 문자열 비교를위한 것입니다. 당신은 아마 원할 것입니다 -lt. 시험:

while [ `ls -1A | grep ^- | wc -l` -lt 3 ]

그러나 여기서 찾기를 사용합니다.

while [ `find . -maxdepth 1 -type f -print | wc -l` -lt 3 ]

하나 이상의 파일 이름에 '$ \ n'이 있으면 둘 다 실패합니다.
Rany Albeg Wein

-1

파싱 하는 것이 죄 라는 것을 알고 있습니다 ls.

find . -type f -maxdepth 1 | xargs ls -ltr | sed '1,3d' | awk '{print $9}' | xargs rm

5 개의 빈 파일로 빠른 테스트 :

$ >1
$ >2
$ >3
$ >4
$ >5
$ find . -type f -maxdepth 1 | xargs ls -lt | sed '1,3d' | awk '{print $9}' | xargs rm
$ ls -1
3
4
5

이것은 두 가지 이유로 실패합니다- ls출력을 파싱 하고 잘못된 방식으로 사용 find하고 xargs함께 사용 하십시오. 당신이 결합 할 경우, find그리고 xargs당신이 사용하는 것이 좋습니다 find-print0따라 xargss의 -O옵션을. 주제에 대한 자세한 정보는 찾기 사용 에 대해 읽으십시오 . 파싱 ​​ls 가 왜 그렇게 나쁜지 살펴보고 싶을 수도 있습니다 .
Rany Albeg Wein

-2

이 하나의 라이너는 내가 생각하는 모든 것을합니다.

ls -t1 /home/user/test | tail -n +4 | xargs -I{} rm -- "{}"

ls는 대화식으로 파일 정보를 보는 도구입니다. 출력은 사람을 위해 형식화되며 스크립트에서 버그가 발생합니다. 글로브를 사용하거나 대신 찾으십시오. 이유를 이해하십시오 : mywiki.wooledge.org/ParsingLs
Rany Albeg Wein

-2

해결책은 다음과 같습니다.

rm /appserver/webapplogs/$(ls -t1 /appserver/webapplogs/|tail -1)

1
@bakbak ls는 대화식으로 파일 정보를 보는 도구입니다. 출력은 사람을 위해 형식화되며 스크립트에서 버그가 발생합니다. 이유를 이해하려면 여기를보십시오 . 답변에 대해 구체적으로 말하면-하나 이상의 파일에 $ '\ n'문자가 포함되어 있으면이 파일이 손상됩니다. 또한 Command Substitution (예 : $ (...))에는 큰 따옴표가 없어서 또 다른 중요한 주제 인 Word Splitting이 나타납니다 !
Rany Albeg Wein
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.