디렉토리 트리에서 가장 오래된 파일을 찾을 수있는 쉘 원 라이너를 찾고 있습니다.
디렉토리 트리에서 가장 오래된 파일을 찾을 수있는 쉘 원 라이너를 찾고 있습니다.
답변:
이것은 작동합니다 (Daniel Andersson의 제안을 통합하여 업데이트되었습니다).
find -type f -printf '%T+ %p\n' | sort | head -n 1
find
파일 이름에 줄 바꿈이 포함되어 있기 때문에 첫 번째 줄 이 비어 있기 때문에 빈 공간이 생깁니다 .
이것은 좀 더 이식성이 뛰어나고 GNU find
확장 에 의존하지 않기 때문에 -printf
BSD / OS X에서도 작동합니다.
find . -type f -print0 | xargs -0 ls -ltr | head -n 1
여기에 유일한 단점은 크기에 다소 제한 점이다 ARG_MAX
( 해야 대부분의 최신 커널에 대한 관련성이없는). 따라서 getconf ARG_MAX
반환 된 문자 (시스템에서 262,144) 이상이 반환되면 올바른 결과를 얻지 못합니다. 또한 POSIX 호환 때문이 아니다 -print0
및 xargs -0
없습니다.
이 문제에 대한 몇 가지 해결책은 다음과 같습니다. 디렉토리에서 최신 (최신, 가장 오래된, 가장 오래된) 파일을 어떻게 찾을 수 있습니까? – 그렉의 위키
xargs: ls: terminated by signal 13
부작용으로 오류가 발생합니다. SIGPIPE 인 것 같아요. 솔루션의 결과를 정렬하기 위해 파이프 정렬 출력을 파이프 할 때 왜 비슷한 오류가 발생하지 않는지 모르겠습니다.
head
한 줄을 읽은 후에 종료되어 파이프를 "파괴"하는 명령이라고 생각합니다. sort
그것에 대해 불평하는 것 같지 않지만 ls
다른 경우 에는 오류가 발생하므로 오류가 발생 하지 않습니다 .
xargs
호출해야하는 파일 이름이 너무 많으면 중단됩니다 ls
. 이 경우 여러 호출의 정렬 된 출력은 병합되어야 할 때 연결됩니다.
ls
그것과 가장 오래된 파일을 안구, 솔루션은 아마 것이다 일으키는 원인이되는 명령 줄 길이 제한을 오버런 ls
여러 번 호출 할 수 있습니다. 당신은 틀린 답을 얻을 것이지만 결코 알지 못할 것입니다.
다음 명령 명령은 모든 종류의 이상한 파일 이름으로 작동합니다.
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 -n
Unix epoch가 조금 더 빠르기 때문에 초 단위로 숫자 정렬 ( )됩니다. sed는 유닉스 시대 이후 초를 삭제합니다.
마지막 명령은 전혀 변환되지 않으며 처음 두 명령보다 훨씬 빠릅니다. find 명령 자체는 가장 오래된 파일의 mtime을 표시하지 않으므로 stat가 필요합니다.
허용 된 답변과 다른 사람들이 여기에서 일하지만, 매우 큰 나무가 있으면 모든 파일을 정렬합니다.
우리가 그것들을 나열하고 정렬 할 필요없이 가장 오래된 것을 추적 할 수 있다면 더 좋을 것입니다.
그래서이 대안 솔루션을 생각해 냈습니다.
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}'
명령 설명 :
그것을 실행 :
~ $ 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}'
ls
출력이 기계를 위해 의미되지 않는 스크립트에 대한 나쁜, 출력 형식은 구현에 걸쳐 다양합니다. 이미 언급했듯이 find
스크립팅에는 좋지만 ls
솔루션 에 대해 말하기 전에 해당 정보를 추가하는 것이 좋습니다 .
ls를 사용하십시오-매뉴얼 페이지는 디렉토리를 주문하는 방법을 알려줍니다.
ls -clt | head -n 2
-n 2는 출력에서 "전체"를 얻지 못합니다. 파일 이름 만 원하면
ls -t | head -n 1
그리고 정상적인 순서로 목록이 필요한 경우 (최신 파일 가져 오기)
ls -tr | head -n 1
찾기를 사용하는 것보다 훨씬 쉽고 빠르며 강력합니다. 파일 이름 형식에 대해 걱정할 필요가 없습니다. 거의 모든 시스템에서도 작동합니다.
find ! -type d -printf "%T@ %p\n" | sort -n | head -n1
sort -n
.
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
두 번째 열, 즉 파일 이름을 표시합니다.
find -type f -printf '%T+ %p\n' | sort | head -1