하위 디렉토리와 시간이있는 디렉토리에서 최근 수정 된 파일을 재귀 적으로 찾고 나열하는 방법은 무엇입니까?


417
  • 운영 체제 : Linux

  • 파일 시스템 유형 : ext3

  • 선호 솔루션 : bash (script / oneliner), ruby, python

하위 디렉토리와 파일이 여러 디렉토리에 있습니다. 모든 첫 번째 레벨 디렉토리가 가장 최근에 작성 / 수정 된 파일의 날짜 및 시간 옆에 나열되도록 구성되는 모든 디렉토리 목록을 작성해야합니다.

명확히하기 위해 파일을 터치하거나 그 내용을 몇 개의 하위 디렉토리 수준 아래로 수정하면 해당 타임 스탬프가 첫 번째 수준의 디렉토리 이름 옆에 표시되어야합니다. 다음과 같은 구조의 디렉토리가 있다고 가정하십시오.

./alfa/beta/gamma/example.txt

그리고 나는 파일의 내용을 수정합니다. example.txt시간 alfa은 인간이 읽을 수있는 형태로 첫 번째 수준 디렉토리 옆에 표시되는 시간이 필요합니다 . 나는 찾기를 사용하여 몇 가지를 시도했습니다 xargs, sort및 좋아하지만 난 '알파'의 파일 시스템 타임 스탬프 내가 만들 때 / 변경 파일 몇 수준을 수정하지 않는 문제를 주변에 얻을 수 없습니다.


그것을 만드는 데 어려움을 겪을 수 있다면 github.com/shadkam/recentmost를 사용할 수 있습니다.
user3392225

4
놀랄 만한. 16 개 답변, 대부분은 / 모든도 ... 영업 이익은 지정된 일을하려고하지 않습니다
hmijail의 신음이 resignees

-R 스위치와 같은 솔루션 대신 여기서 대량으로 볼 수 있습니다.
neverMind9

기본 기능이어야합니다.
neverMind9 2016 년

답변:


486

이거 한번 해봐:

#!/bin/bash
find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

재귀 적으로 스캔을 시작해야하는 디렉토리의 경로를 사용하여 실행하십시오 (공백이있는 파일 이름을 지원함).

많은 파일이 있으면 무언가를 반환하기까지 시간이 걸릴 수 있습니다. xargs대신 사용하면 성능을 향상시킬 수 있습니다 .

#!/bin/bash
find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head

조금 더 빠릅니다.


132
"빠른 방법"은 print0을 사용하여 파일 이름에서 공백과 심지어 줄 바꿈도 지원할 수 있어야합니다. 여기 내가 사용하는 것이 있습니다 : find $1 -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head 이것은 여전히 ​​나를 위해 빠릅니다.
Dan

20
Mac OS X에서는 GNU의 통계가 아니므로 명령이 실패합니다. 당신은에있는 brew install coreutils사용 gstat대신에stat
CharlesB

36
작업 을 수행하기 stat때문에 실행할 필요가 없습니다 find PATH -type f -printf "%T@ %p\n"| sort -nr. 그런 식으로 조금 더 빠릅니다.
nr

4
@ user37078의 의견을 실제 답변으로 바꾸거나 원래 답변을 편집 할 수 있습니까? 그것을하는 것이 "올바른 방법"[tm] 인 것 같습니다.
mnagel

6
Mac OS X에서 gstat 또는 다른 것을 설치하지 않고도 다음을 수행 할 수 있습니다.find PATH -type f -exec stat -f "%m %N" "{}" \; | sort -nr | head
cobbzilla

198

N 분 전에 파일 상태가 마지막으로 변경된 모든 파일을 찾으려면 다음을 수행하십시오 .

find -cmin -N

예를 들면 다음과 같습니다.

find -cmin -5


4
+1 감사합니다. 매우 유용합니다. GnuWin32 찾기를 사용하여 Windows에서 작동합니다.
Sabuncu

매우 간결합니다. 아주 좋아요!
랜디 L

다른 솔루션보다 더 빠릅니다.
david.perez

20
또한 지난 50 일 동안 'find -ctime -50'을 사용할 수도 있습니다.
Gorkem

1
혼란을 sudo find -cmin -1 2>&1 |grep -v /proc/
없애

39

GNU Find (참조 man find)에는 -printf파일 EPOC mtime 및 상대 경로 이름을 표시 하는 매개 변수가 있습니다.

redhat> find . -type f -printf '%T@ %P\n' | sort -n | awk '{print $2}'

3
감사! 이것은 합리적인 시간에 매우 넓은 디렉토리 구조를 검색하기에 충분히 빠른 유일한 대답입니다. 출력에 tail수천 줄이 인쇄되지 않도록 출력을 통과 시킵니다.
sffc

8
또 다른 의견 : awk '{print $2}'공백이있는 파일 이름이있을 때 부분이 문제를 일으키는 것으로 보입니다. 다음은 sed대신 사용하는 솔루션 이며 경로와 함께 시간을 인쇄합니다.find . -type f -printf '%T@ %Tc %P\n' | sort -n | tail | sed -r 's/^.{22}//'
sffc

3
나는 그것이 정렬되어야한다고 생각한다
Bojan Dević

2
-printf 변형은 매번 'stat'프로세스를 호출하는 것보다 훨씬 빠릅니다. 백업 작업 시간이 줄어 듭니다. 이 사실을 알려 주셔서 감사합니다. 트리의 마지막 업데이트에만 관심이 있으므로 awk / sed를 피했습니다. 따라서 X = $ (find / path -type f -printf '% T % p \ n'| grep -v something-I- 돈-tcare-에 대한 | 종류의 -nr | 1 -n 머리)와 에코 $ {X # * "는"} 나) 최초의 우주까지 물건을주고 (나를 위해 잘 작동
데이비드 굿윈

2
파일 이름이 여러 줄에 걸쳐 있으면 모두 작동하지 않습니다. touch "lala<Enter>b"이러한 파일을 작성하는 데 사용하십시오 . 유닉스 유틸리티 디자인은 파일 이름에 큰 결함이 있다고 생각합니다.
과일

35

이 원 라이너에 대한 후광의 멋진 답변을 단축했습니다.

stat --printf="%y %n\n" $(ls -tr $(find * -type f))

업데이트 : 파일 이름에 공백이 있으면이 수정을 사용할 수 있습니다

OFS="$IFS";IFS=$'\n';stat --printf="%y %n\n" $(ls -tr $(find . -type f));IFS="$OFS";

어떻습니까 : IFS = $ '\ n'; stat --printf = "% y % n \ n"$ (ls -tr $ (find. -type f))
slashdottir

3
파일 수가 매우 많으면 작동하지 않습니다. xargs를 사용하는 답변은 그 한계를 해결합니다.
carl verbiest

@carlverbiest는 실제로 많은 파일이 slashdottir의 솔루션을 손상시킵니다. xargs 기반 솔루션조차 느려질 것입니다. user2570243의 솔루션 은 큰 파일 시스템에 가장 적합합니다.
Stéphane Gourichon

IFS=$'\n'파일 이름을 처리 할 때 어떤 경우에도 안전하지 않습니다. 줄 바꿈은 UNIX의 파일 이름에 유효한 문자입니다. NUL 문자 만 경로에 존재하지 않아야합니다.
Charles Duffy

17

이 시도

#!/bin/bash
stat --format %y $(ls -t $(find alfa/ -type f) | head -n 1)

그것은 사용 find, 디렉토리에서 모든 파일을 수집하는 ls그들, 수정 날짜별로 정렬 목록에 head첫 번째 파일을 선택하고 마지막으로 stat멋진 형식으로 시간을 표시 할 수 있습니다.

현재 이름에 공백이나 다른 특수 문자가있는 파일은 안전하지 않습니다. 아직 귀하의 요구를 충족시키지 못하면 칭찬을 작성하십시오.


1
후광 : 나는 당신의 대답을 좋아합니다, 그것은 잘 작동하고 올바른 파일을 인쇄합니다. 내 경우에는 너무 많은 하위 수준이 있기 때문에 도움이되지 않습니다. 그래서 나는 ls에 대해 "인수 목록이 너무 깁니다"를 얻습니다. 나는 다른 것을 시도 할 것이다.
fredrik

이 경우 좀 더 복잡하고 실제 프로그램이 필요합니다. 나는 펄을 해킹 할 것이다.
Daniel Böhmer

1
대신 PHP를 사용 하여이 문제를 해결했습니다. 파일 시스템 트리에서 내려와 가장 최근에 수정 된 파일의 시간을 저장하는 재귀 함수입니다.
fredrik

11

이 명령은 Mac OS X에서 작동합니다.

find "$1" -type f -print0 | xargs -0 stat --format '%Y :%y %n' | sort -nr | cut -d: -f2- | head

Linux에서는 원래 포스터가 요청한대로 stat대신gstat .

물론이 답변은 user37078 의 뛰어난 솔루션으로, 의견에서 전체 답변으로 승격되었습니다. Mac OS X 에서 사용하기 위해 CharlesB 의 통찰력을 혼합했습니다. homebrew 대신 MacPorts 에서 coreutilsgstat얻었습니다. .

그리고 이것을 ~/bin/ls-recent.sh재사용 을위한 간단한 명령으로 패키지화 한 방법이 있습니다 :

#!/bin/bash
# ls-recent: list files in a dir tree, most recently modified first
#
# Usage: ls-recent path [-10 | more]
# 
# Where "path" is a path to target directory, "-10" is any arg to pass
# to "head" to limit the number of entries, and "more" is a special arg
# in place of "-10" which calls the pager "more" instead of "head".
if [ "more" = "$2" ]; then
   H=more; N=''
else
   H=head; N=$2
fi

find "$1" -type f -print0 |xargs -0 gstat --format '%Y :%y %n' \
    |sort -nr |cut -d: -f2- |$H $N

2
OS X 요세미티에서; 오류가 발생합니다 : 찾기 : ftsopen : 해당 파일 또는 디렉토리가 없습니다
Reece

흥미 롭군 어떤 명령을 매개 변수와 함께 입력 했습니까? 그리고 그 디렉토리에있는 파일의 이름은 무엇입니까? 그리고 자신 만의 버전을 만든 경우 ~/bin/ls-recent.sh스크립트에서 차이점을주의 깊게 검사 했습니까?
Jim DeLaHunt

10
Mac OS X에 아무것도 설치하고 싶지 않은 사람들을 위해 :find . -exec stat -f '%m%t%Sm %N' {} + | sort -n | cut -f2-
Jake

5

모두이 게시물의 펄과 파이썬 솔루션은 나 맥 OS X에서이 문제를 해결 도움 : /unix/9247/how-to-list-files-sorted-by-modification-date-recursively -no-stat-command-avail .

게시물에서 인용 :

펄 :

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        print sort {$_{$b} <=> $_{$a}} keys %_;  # print by decreasing age
    }'

파이썬 :

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in sorted(times.iterkeys(), key=lambda f:times[f]): print f'

5

멋지고 빠른 타임 스탬프와 함께 숨겨진 파일 무시

파일 이름의 공백을 잘 처리해야합니다.

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

2017.01.28 07h00 Sat ./recent
2017.01.21 10h49 Sat ./hgb
2017.01.16 07h44 Mon ./swx
2017.01.10 18h24 Tue ./update-stations
2017.01.09 10h38 Mon ./stations.json

find풍부한 맛이 링크를 따라 찾을 수 있습니다.


3

최신 액세스 시간에 대해 이것을 보여 주므로 최신 모드 시간을 수행하도록 쉽게 수정할 수 있습니다.

이를 수행하는 두 가지 방법이 있습니다.


1) 수백만 개의 파일이 있으면 비쌀 수있는 전역 정렬을 피하려면 다음을 수행하십시오. (검색을 시작하려는 디렉토리의 루트에 자신을 배치하십시오)

linux> touch -d @0 /tmp/a;
linux> find . -type f -exec tcsh -f -c test `stat --printf="%X" {}` -gt  `stat --printf="%X" /tmp/a`  ; -exec tcsh -f -c touch -a -r {} /tmp/a ; -print 

위의 방법은 점진적으로 새로운 액세스 시간으로 파일 이름을 인쇄하며 마지막으로 인쇄 된 파일은 최신 액세스 시간을 가진 파일입니다. "tail -1"을 사용하여 최신 액세스 시간을 확보 할 수 있습니다.


2) 당신은 재귀 적으로 서브 디렉토리에있는 모든 파일의 이름, 액세스 시간을 인쇄 한 다음 액세스 시간과 꼬리를 기준으로 정렬 할 수 있습니다.

linux> \find . -type f -exec stat --printf="%X  %n\n" {} \; | \sort -n | tail -1

그리고 당신은 그것을 가지고 ...


3

내 프로필 에이 별칭이있어 자주 사용합니다.

$ alias | grep xlogs
xlogs='sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R'

그래서 당신이 찾고있는 것을 수행합니다 (단, 날짜 / 시간을 여러 수준으로 변경하지는 않습니다)-최신 파일 (이 경우 * .log 및 * .trc 파일)을 찾습니다. 또한 마지막 날에 수정 된 파일 만 찾은 다음 시간별로 정렬하고 출력을 줄입니다.

sudo find . \( -name "*.log" -o -name "*.trc" \) -mtime -1 | sudo xargs ls -ltr --color | less -R

추신. 주의 사항 일부 서버에는 루트가 없지만 항상 sudo가 있으므로 해당 부분이 필요하지 않을 수 있습니다.


"정확히 찾고있는 것"은 어떻습니까? OP는 그가 원했던 것에 대한 좋은 설명을 썼습니다. 이것은 완전히 무시합니다.
hmijail는 사임 자 애도

그것을 지적 해 주셔서 감사합니다. 맞습니다.이 방법은 날짜 / 시간을 변경하기 위해 여러 수준으로 이동하지 않으며 그 안에 디렉토리 파일의 날짜 / 시간 만 표시합니다. 내 답변을 편집했습니다.
Tagar

1

당신은 시도 시도의 printf 명령을 줄 수 있습니다

% Ak 파일의 마지막 액세스 시간은 k로 지정된 형식으로 @' or a directive for the C strftime '함수입니다. k의 가능한 값은 다음과 같습니다. 시스템간에 "strftime"의 차이로 인해 일부는 모든 시스템에서 사용 가능하지 않을 수 있습니다.


1

빠른 배쉬 기능 :

# findLatestModifiedFiles(directory, [max=10, [format="%Td %Tb %TY, %TT"]])
function findLatestModifiedFiles() {
    local d="${1:-.}"
    local m="${2:-10}"
    local f="${3:-%Td %Tb %TY, %TT}"

    find "$d" -type f -printf "%T@ :$f %p\n" | sort -nr | cut -d: -f2- | head -n"$m"
}

디렉토리에서 최신 수정 된 파일을 찾으십시오.

findLatestModifiedFiles "/home/jason/" 1

세 번째 인수로 고유 한 날짜 / 시간 형식을 지정할 수도 있습니다.


1

다음은 타임 스탬프 문자열과 가장 최근 타임 스탬프가있는 파일 이름을 반환합니다.

find $Directory -type f -printf "%TY-%Tm-%Td-%TH-%TM-%TS %p\n" | sed -r 's/([[:digit:]]{2})\.([[:digit:]]{2,})/\1-\2/' |     sort --field-separator='-' -nrk1 -nrk2 -nrk3 -nrk4 -nrk5 -nrk6 -nrk7 | head -n 1

다음과 같은 형식의 출력 결과 : <yy-mm-dd-hh-mm-ss.nanosec> <filename>


1

다음은 공백, 줄 바꿈, glob 문자를 포함 할 수있는 파일 이름과 함께 작동하는 버전입니다.

find . -type f -printf "%T@ %p\0" | sort -zk1nr
  • find ... -printf파일 수정 (EPOCH 값) 다음에 공백과 \0종료 된 파일 이름을 인쇄합니다 .
  • sort -zk1nr NUL로 종료 된 데이터를 읽고 역순으로 정렬

질문에 Linux 태그가 붙어 있으므로 가정합니다. gnu 유틸리티를 사용할 수 합니다.

위의 파이프를 사용하여 다음을 수행 할 수 있습니다.

xargs -0 printf "%s\n"

줄 바꿈으로 끝나는 수정 시간 (가장 최근의 첫 번째)으로 정렬 된 수정 시간 및 파일 이름을 인쇄합니다.


1

이것이 내가 사용하는 것입니다 (매우 효율적).

function find_last () { find "${1:-.}" -type f -printf '%TY-%Tm-%Td %TH:%TM %P\n' 2>/dev/null | sort | tail -n "${2:-10}" }

장점 :

  • 3 개의 프로세스 만 생성합니다

용법:

find_last [dir [number]]

어디:

  • dir -검색 할 디렉토리 [현재 디렉토리]
  • number -표시 할 최신 파일 수 [10]

출력 결과는 find_last /etc 4다음과 같습니다.

2019-07-09 12:12 cups/printers.conf
2019-07-09 14:20 salt/minion.d/_schedule.conf
2019-07-09 14:31 network/interfaces
2019-07-09 14:41 environment

0

일반 ls출력의 경우 이것을 사용하십시오. 인수 목록이 없으므로 너무 길어질 수 없습니다 :

find . | while read FILE;do ls -d -l "$FILE";done

cut날짜, 시간 및 이름만으로 멋지게 꾸미십시오 .

find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5

편집 : 방금 현재 최고 답변이 수정 날짜별로 정렬됩니다. 수정 날짜가 각 줄에서 첫 번째이므로 끝 부분에 정렬하기 때문에 두 번째 예제와 마찬가지로 쉽습니다.

find . | while read FILE;do ls -d -l "$FILE";done | cut --complement -d ' ' -f 1-5 | sort

0

이것은 bash에서도 재귀 함수로 수행 할 수 있습니다

F를 사전 순으로 정렬 가능한 yyyy-mm-dd 등이어야하는 파일 시간을 표시하는 함수를 시키십시오 (OS에 따라 다릅니 까?).

F(){ stat --format %y "$1";}                # Linux
F(){ ls -E "$1"|awk '{print$6" "$7}';}      # SunOS: maybe this could be done easier

R 디렉토리를 통해 실행되는 재귀 함수

R(){ local f;for f in "$1"/*;do [ -d "$f" ]&&R $f||F "$f";done;}

그리고 마지막으로

for f in *;do [ -d "$f" ]&&echo `R "$f"|sort|tail -1`" $f";done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.