디렉토리 트리에서 가장 오래된 파일을 어떻게 찾을 수 있습니까


답변:


72

이것은 작동합니다 (Daniel Andersson의 제안을 통합하여 업데이트되었습니다).

find -type f -printf '%T+ %p\n' | sort | head -n 1

8
타이핑이 find -type f -printf '%T+ %p\n' | sort | head -1
Daniel Andersson

1
find파일 이름에 줄 바꿈이 포함되어 있기 때문에 첫 번째 줄 이 비어 있기 때문에 빈 공간이 생깁니다 .
林果 皞

1
생성 날짜 또는 수정 날짜를 사용하는지 물어볼 수 있습니까?
MrMesees

1
리눅스는 파일 생성 날짜를 어디에도 저장하지 않습니다 [*]. 수정 날짜를 사용합니다. [*] 이것은 사실이 아닙니다. ext4는 inode 생성 날짜를 저장하지만 시스템 호출을 통해 노출되지 않으며이를 보려면 debugfs를 사용해야합니다.)
Marius Gedminas

11

이것은 좀 더 이식성이 뛰어나고 GNU find확장 에 의존하지 않기 때문에 -printfBSD / OS X에서도 작동합니다.

find . -type f -print0 | xargs -0 ls -ltr | head -n 1

여기에 유일한 단점은 크기에 다소 제한 점이다 ARG_MAX( 해야 대부분의 최신 커널에 대한 관련성이없는). 따라서 getconf ARG_MAX반환 된 문자 (시스템에서 262,144) 이상이 반환되면 올바른 결과를 얻지 못합니다. 또한 POSIX 호환 때문이 아니다 -print0xargs -0없습니다.

이 문제에 대한 몇 가지 해결책은 다음과 같습니다. 디렉토리에서 최신 (최신, 가장 오래된, 가장 오래된) 파일을 어떻게 찾을 수 있습니까? – 그렉의 위키


이것도 작동하지만 xargs: ls: terminated by signal 13부작용으로 오류가 발생합니다. SIGPIPE 인 것 같아요. 솔루션의 결과를 정렬하기 위해 파이프 정렬 출력을 파이프 할 때 왜 비슷한 오류가 발생하지 않는지 모르겠습니다.
Marius Gedminas

또한 버전은 메모리에서 입력하기가 더 쉽습니다. :-)
Marius Gedminas

예, 파이프가 파손되었습니다. 나는 모든 명령의 GNU 및 BSD 버전 모두에서 이것을 얻지 못하지만 head한 줄을 읽은 후에 종료되어 파이프를 "파괴"하는 명령이라고 생각합니다. sort그것에 대해 불평하는 것 같지 않지만 ls다른 경우 에는 오류가 발생하므로 오류가 발생 하지 않습니다 .
slhck

4
두 번 이상 xargs호출해야하는 파일 이름이 너무 많으면 중단됩니다 ls. 이 경우 여러 호출의 정렬 된 출력은 병합되어야 할 때 연결됩니다.
Nicole Hamilton

2
파일 이름에 공백이 없다고 가정하는 스크립트를 게시하는 것보다 나쁘다고 생각합니다. 파일 이름에 공백이 없기 때문에 많은 시간이 걸립니다. 그리고 그들이 실패하면 오류가 발생합니다. 그러나 이것은 실제 상황에서는 작동하지 않을 것이며 실패는 발견되지 않을 것입니다. 그냥 충분히 큰 디렉토리 트리에서 해당 작업을 수행 할 수 있습니다 ls그것과 가장 오래된 파일을 안구, 솔루션은 아마 것이다 일으키는 원인이되는 명령 줄 길이 제한을 오버런 ls여러 번 호출 할 수 있습니다. 당신은 틀린 답을 얻을 것이지만 결코 알지 못할 것입니다.
니콜 해밀턴

11

다음 명령 명령은 모든 종류의 이상한 파일 이름으로 작동합니다.

find -type f -printf "%T+ %p\0" | sort -z | grep -zom 1 ".*" | cat

find -type f -printf "%T@ %T+ %p\0" | \
    sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //'

stat -c "%y %n" "$(find -type f -printf "%T@ %p\0" | \
    sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //')"

\0줄 바꿈 문자 ( ) 대신 널 바이트 ( )를 사용 \n하면 파일 이름 중 하나에 줄 바꿈 문자가 포함 된 경우 find 출력을 여전히 이해할 수 있습니다.

-z스위치는 sort와 grep이 모두 널 바이트 만 행 끝 문자로 해석하도록합니다. 헤드에는 이러한 스위치가 없으므로 grep -m 1대신 한 번만 사용 합니다.

명령은 실행 시간에 따라 정렬됩니다 (시스템에서 측정).

  • 첫 번째 명령은 모든 파일의 mtime을 사람이 읽을 수있는 형식으로 먼저 변환 한 다음 해당 문자열을 정렬해야하기 때문에 속도가 가장 느립니다. 고양이에게 배관하면 출력물이 채색되지 않습니다.

  • 두 번째 명령은 약간 빠릅니다. 여전히 날짜 변환을 수행하는 동안 sort -nUnix epoch가 조금 더 빠르기 때문에 초 단위로 숫자 정렬 ( )됩니다. sed는 유닉스 시대 이후 초를 삭제합니다.

  • 마지막 명령은 전혀 변환되지 않으며 처음 두 명령보다 훨씬 빠릅니다. find 명령 자체는 가장 오래된 파일의 mtime을 표시하지 않으므로 stat가 필요합니다.

관련 매뉴얼 페이지 : 찾기grepsed정렬stat


5

허용 된 답변과 다른 사람들이 여기에서 일하지만, 매우 큰 나무가 있으면 모든 파일을 정렬합니다.

우리가 그것들을 나열하고 정렬 할 필요없이 가장 오래된 것을 추적 할 수 있다면 더 좋을 것입니다.

그래서이 대안 솔루션을 생각해 냈습니다.

ls -lRU $PWD/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($1,0,1)=="/") { pat=substr($1,0,length($0)-1)"/"; }; if( $6 != "") {if ( $6 < oldd ) { oldd=$6; oldf=pat$8; }; print $6, pat$8; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'

질문이 조금 오래된 경우에도 도움이되기를 바랍니다.


편집 1 : 이 변경으로 파일과 디렉토리를 공백으로 파싱 할 수 있습니다. 루트에서 발행 /하고 가장 오래된 파일을 찾을 수 있을 정도로 빠릅니다 .

ls -lRU --time-style=long-iso "$PWD"/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($0,0,1)=="/") { pat=substr($0,0,length($0)-1)"/"; $6="" }; if( $6 ~ /^[0-9]+$/) {if ( $6 < oldd ) { oldd=$6; oldf=$8; for(i=9; i<=NF; i++) oldf=oldf $i; oldf=pat oldf; }; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'

명령 설명 :

  • ls -lRU --time-style = long-iso "$ PWD"/ *는 모든 파일 (*), 긴 형식 (l), 재귀 적으로 (R), 정렬 (U)없이 빠르게 나열하고 awk로 파이프합니다.
  • Awk는 카운터를 제로 카운터 (이 질문에 선택 사항)로 시작하고 가장 오래된 날짜를 오늘로 설정하여 YearMonthDay 형식으로 시작합니다.
  • 메인 루프 우선
    • 6 번째 필드, 날짜, 년-월-일 형식을 잡고 YearMonthDay로 변경하십시오 (이 방법으로 ls가 출력되지 않으면 미세 조정해야 할 수도 있습니다).
    • 재귀를 사용하면 / directory / here : 형식으로 모든 디렉토리에 대한 헤더 행이 있습니다. 이 줄을 pat 변수로 가져옵니다. (마지막 ":"을 "/"로 대체). 그리고 헤더 행을 유효한 파일 행으로 사용하지 않도록 $ 6을 아무것도 설정하지 않습니다.
    • $ 6 필드에 유효한 숫자가 있으면 날짜입니다. 이전 날짜와 비교하십시오.
    • 나이가 더 많습니까? 그런 다음 이전 날짜 oldd 및 이전 파일 이름 oldf에 대한 새 값을 저장하십시오. BTW, oldf는 8 번째 필드 일뿐만 아니라 8 번째 끝까지입니다. 이것이 루프가 8에서 NF (끝)로 연결되는 이유입니다.
    • 한 번씩 진행 카운트
    • 결과를 인쇄하여 종료

그것을 실행 :

~ $ time ls -lRU "$ PWD"/ * | awk 등

가장 오래된 날짜 : 19691231

파일 : /home/.../.../backupold/.../EXAMPLES/how-to-program.txt

총 비교 : 111438

실제 0m1.135s

사용자 0m0.872s

시스 0m0.760s


편집 2 : 같은 개념을 사용하여 더 나은 솔루션 find상기보고 접근 시간 (사용 %T처음으로 printf에 대한 수정 시간 또는 %C대한 상태 변경 대신).

find . -wholename "*" -type f -printf "%AY%Am%Ad %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'

편집 3 : 다음 명령은 수정 시간을 사용 하고 오래된 파일과 오래된 파일을 찾을 때 증분 진행률을 인쇄합니다. 1970-1-01과 같은 잘못된 타임 스탬프가있을 때 유용합니다.

find . -wholename "*" -type f -printf "%TY%Tm%Td %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; print oldd " " oldf; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'

공백이있는 파일을 허용하려면 여전히 tweeking이 필요합니다. 곧 할게요
Dr Beco

공백이있는 파일의 ls 구문 분석은 좋은 생각이 아닙니다. 아마도 find를 사용했을 것입니다.
Dr Beco

전체 트리 "/"에서 실행하십시오. 소요 시간 : 총 비교 : 585744 실제 2m14.017s 사용자 0m8.181s sys 0m8.473s
Dr Beco

사용하여 ls출력이 기계를 위해 의미되지 않는 스크립트에 대한 나쁜, 출력 형식은 구현에 걸쳐 다양합니다. 이미 언급했듯이 find스크립팅에는 좋지만 ls솔루션 에 대해 말하기 전에 해당 정보를 추가하는 것이 좋습니다 .
Sampo Sarrala

4

ls를 사용하십시오-매뉴얼 페이지는 디렉토리를 주문하는 방법을 알려줍니다.

ls -clt | head -n 2

-n 2는 출력에서 ​​"전체"를 얻지 못합니다. 파일 이름 만 원하면

ls -t | head -n 1

그리고 정상적인 순서로 목록이 필요한 경우 (최신 파일 가져 오기)

ls -tr | head -n 1

찾기를 사용하는 것보다 훨씬 쉽고 빠르며 강력합니다. 파일 이름 형식에 대해 걱정할 필요가 없습니다. 거의 모든 시스템에서도 작동합니다.


6
이것은 파일이 단일 디렉토리에있는 경우에만 작동하며 내 질문은 디렉토리 트리에 관한 것입니다.
Marius Gedminas

2
find ! -type d -printf "%T@ %p\n" | sort -n | head -n1

2001 년 9 월 9 일 (유닉스 시대 이후 1000000000 초)보다 오래된 파일이 있으면 제대로 작동하지 않습니다. 숫자 정렬을 사용하려면을 사용하십시오 sort -n.
Dennis

이것은 나에게 파일을 찾을 수 있지만, 두 번째 명령 : 실행하지 않고 그것이 얼마나 오래된 볼 어렵다
마리우스 Gedminas

0

대부분의 사람들은 "가장 오래된"것으로 "가장 오래된 수정 시간"을 의미한다고 가정합니다. "가장 오래된"에 대한 가장 엄격한 해석에 따르면 아마도 수정되었지만 액세스 시간 이 가장 오래된 것을 원할 경우 가장 좋은 답변을 수정합니다.

find -type f -printf '%A+ %p\n' | sort | head -n 1

를 확인하십시오 %A+.


-1
set $(find /search/dirname -type f -printf '%T+ %h/%f\n' | sort | head -n 1) && echo $2
  • find ./search/dirname -type f -printf '%T+ %h/%f\n' 날짜와 파일 이름을 두 열로 인쇄합니다.
  • sort | head -n1 가장 오래된 파일에 해당하는 줄을 유지합니다.
  • echo $2 두 번째 열, 즉 파일 이름을 표시합니다.

1
슈퍼 유저에 오신 것을 환영합니다! 이것이 질문에 대한 답변이 될 수 있지만 그 이유를 설명 할 수 있다면 더 나은 답변이 될 것 입니다.
DavidPostill

1
여러 사람들이 이전의 (동일한) 삭제 된 답변에 대한 설명을 요청했습니다.
DavidPostill

대답하기 어려운 것은 무엇입니까? ./search/dirname -type f -printf '% T + % h / % f \ n'찾기 | 정렬 | head -n 1 파일의 시간과 경로로 두 개의 열을 표시합니다. 첫 번째 열을 제거해야합니다. set and echo $ 2 사용
Dima

1
다른 여러 사용자가 요청한대로 명령 행을 붙여 넣는 대신 설명을 제공해야합니다.
Ob1lan

1
이것이 받아 들인 대답과 어떻게 다릅니 까?
Ramhound
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.