it-gundan.com

서브 디렉토리와 시간이있는 디렉토리에서 최신 수정 된 파일을 재귀 적으로 찾고 나열하는 방법?

  • 운영 체제 : Linux

  • 파일 시스템 유형 : ext3

  • 선호하는 솔루션 : bash (스크립트/oneliner), Ruby, python

몇 가지 하위 디렉토리와 파일이있는 여러 디렉토리가 있습니다. 모든 첫 번째 수준의 디렉터리가 그 안에 최근에 만들어진/수정 된 파일의 날짜와 시간 옆에 나열되도록 구성된 모든 디렉터리의 목록을 만들어야합니다.

내가 파일을 터치하거나 내용의 하위 디렉토리 레벨을 몇 개 수정하면 그 첫 번째 레벨 디렉토리 이름 옆에 타임 스탬프가 표시되어야합니다. 다음과 같이 구조화 된 디렉토리가 있다고 가정 해보십시오.

./alfa/beta/gamma/example.txt

example.txt 파일의 내용을 수정합니다. 그 시간은 Epoch가 아닌 사람이 읽을 수있는 형식으로 alfa의 첫 번째 수준 디렉토리 옆에 표시해야합니다. find, xargs, sort 등을 사용하여 몇 가지 작업을 시도했지만 몇 레벨 아래로 파일을 만들거나 수정할 때 'alfa'의 파일 시스템 타임 스탬프가 변경되지 않는 문제를 해결할 수 없습니다.

364
fredrik

이거 한번 해봐:

#!/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

조금 더 빠릅니다.

427
Heppo

파일 상태가 마지막으로 변경된 모든 파일을 찾으려면Nminutes ago :

find -cmin -N

예 :

find -cmin -5

168
iman

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

redhat> find . -type f -printf '%[email protected] %P\n' | sort -n | awk '{print $2}'
37
user2570243

나는이 한줄기에 대한 후광의 끔찍한 대답을 단축했다.

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

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

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

이 시도

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

find을 사용하여 디렉토리의 모든 파일을 수집하고 ls을 사용하여 수정 날짜순으로 정렬하고 head을 사용하여 첫 번째 파일을 선택하고 마지막으로 stat을 사용하여 니스 형식으로 표시합니다.

현재 공백 문자 나 다른 특수 문자가있는 파일은 안전하지 않습니다. 그것이 당신의 필요를 아직 충족시키지 못하면 칭찬을 씁니다.

13
Daniel Böhmer

이 명령은 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에서 gstat을 사용하기 위해 CharlesB 의 통찰을 혼합했습니다. 그런데 homeprew 대신 MacPorts 에서 coreutils를 얻었습니다.

그리고 이것을 재사용을 위해 간단한 명령 ~/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
10
Jim DeLaHunt

이 게시물에있는 Perl과 Python 솔루션 모두 Mac OS X에서이 문제를 해결하는 데 도움이되었습니다. https://unix.stackexchange.com/questions/9247/how-to-list-files-sorted-by-modification-date -recursively-no-stat-command-avail .

게시물에서 인용 :

Perl :

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
William Niu

최신 액세스 시간으로 이것을 표시하고 있습니다.이 모드를 수정하여 최신 모드 시간을 쉽게 할 수 있습니다.

이 작업에는 두 가지 방법이 있습니다.


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 

위의 방법은 점진적으로 새로운 액세스 시간으로 파일 이름을 인쇄하고 마지막으로 액세스 한 파일은 최신 액세스 시간을 가진 파일입니다. 분명히 "꼬리 -1"을 사용하여 최신 액세스 시간을 얻을 수 있습니다.


2) 재귀 적으로 이름을 찾아서 하위 디렉토리의 모든 파일에 액세스 한 다음 액세스 시간과 가장 큰 항목을 기준으로 정렬 할 수 있습니다.

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

그리고 거기에 ...

3
Sean

나는 .profile에 아주 자주 사용하는 별명을 가지고있다.

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

그래서 당신이 찾고있는 것을 수행합니다 (예외적으로 그것은 날짜/시간을 여러 단계로 변경하지 않습니다) - 최신 파일 (이 경우에는 .log 및 * .trc 파일)을 찾습니다. 또한 마지막 날에 수정 된 파일을 찾은 다음 시간순으로 정렬하고 less를 통해 파이프 출력을 정렬합니다.

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

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

3
Tagar

숨김 파일 무시 - 멋진 빠른 스탬프 사용

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

$ 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 풍부한 링크를 따라 가면 찾을 수 있습니다.

2
Serge Stroobandt

다음은 공백, 개행 문자, glob 문자를 포함 할 수있는 파일 이름으로 작동하는 하나의 버전입니다.

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

질문으로 리눅스 태그가 지정되었으므로 gnu 유틸리티를 사용할 수 있다고 가정합니다.

위의 파이프는 다음과 같이 연결할 수 있습니다.

xargs -0 printf "%s\n"

개조 시간에 의해 정정 된 수정 시간과 파일 이름을 출력한다.

1
anubhava

빠른 배시 기능 :

# 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 "%[email protected] :$f %p\n" | sort -nr | cut -d: -f2- | head -n"$m"
}

디렉토리에서 최신 수정 된 파일 찾기 :

findLatestModifiedFiles "/home/jason/" 1

세 번째 인수로 자신의 날짜/시간 형식을 지정할 수도 있습니다.

1
Jason Larke

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

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
mark_infinite

Printf 명령을 사용하여 try를 찾을 수 있습니다.

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

0
graugans

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

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
Seweryn Niemiec

이것은 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
0
Nahuel Fouilleul

일반 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

EDIT: 현재 상위 답변이 수정 날짜별로 정렬되었음을 알았습니다. 수정 날짜가 처음부터 각 줄에 있기 때문에 두 번째 예제 에서처럼 쉽습니다. 마지막에 정렬을 적용하십시오.

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