파일 작성 시간을 어떻게 찾습니까?


64

파일의 생성 시간을 찾아야합니다.이 문제에 대한 기사를 읽으면 Site1 , Site2 와 같은 해결책이 없다고 언급했습니다 .

stat명령을 시도하면 상태가 표시 Birth: -됩니다.

그러면 파일 작성 시간을 어떻게 찾을 수 있습니까?


2
파일의 '생성 시간'이 정확한 것은 아닙니다. 파일에서 작성 날짜를 '퍼지'하는 방법에는 여러 가지가 있습니다.
토마스 워드

1
@ThomasWard 다른 파일 데이터를 퍼지하는 방법보다 더 많은가?
Cees Timmerman

답변:


67

디렉토리의 작성 날짜를 알 수있는 방법이 있습니다. 다음 단계를 따르십시오.

  1. 명령으로 디렉토리 의 inode 를 알 ls -i수 있습니다 (예 : X )

  2. df -T /path명령으로 디렉토리가 저장된 파티션을 알 수 있습니다 (켜져 있음 /dev/sda1).

  3. 이제이 명령을 사용하십시오 : sudo debugfs -R 'stat <X>' /dev/sda1

당신은 출력에서 ​​볼 수 있습니다 :

crtime: 0x4e81cacc:966104fc -- mon Sep 27 14:38:28 2013

crtime 은 파일 생성 날짜입니다.

내가 테스트 한 것 :

  1. 특정 시간에 디렉토리를 작성했습니다.
  2. 액세스했습니다.
  3. 파일을 작성하여 수정했습니다.

  4. 나는 명령을 시도하고 정확한 시간을 주었다.

  5. 그런 다음 수정 한 후 다시 테스트하면 crtime 은 동일하게 유지되지만 수정액세스 시간이 변경되었습니다.

나는 내가 더 잘 이해할 수 있도록 토론하고 싶기 때문에 이것을 게시한다. 왜 사람들이 리눅스가이 기능을 지원하지 않는다고 말하는지 궁금하다
nux

13
리눅스 자체는 그렇지 않기 때문입니다. ext4 파일 시스템에는이 정보가 있지만 커널은 액세스 할 수있는 API를 제공하지 않습니다. 분명히 debugfs파일 시스템에서 직접 추출하므로 커널의 API를 사용할 필요가 없습니다. 여기를 참조 하십시오 .
terdon

나는 그것을 테스트했다. 그것은 ext4 파일 시스템에서 완벽하게 작동했습니다
Fahim Babar Patel

1
이것은 ext4에만 해당되는 것 같습니다. XFS에서는 작동하지 않았습니다.
Quantum7

statx()2019
hippietrail

54

@Nux 는이를 위해 훌륭한 솔루션 을 찾았 습니다 . 나는 모든 것을 직접 실행하는 데 사용할 수있는 작은 함수를 작성하기로 결정했습니다. 에 이것을 추가하십시오 ~/.bashrc.

get_crtime() {

    for target in "${@}"; do
        inode=$(stat -c '%i' "${target}")
        fs=$(df  --output=source "${target}"  | tail -1)
        crtime=$(sudo debugfs -R 'stat <'"${inode}"'>' "${fs}" 2>/dev/null | 
        grep -oP 'crtime.*--\s*\K.*')
        printf "%s\t%s\n" "${target}" "${crtime}"
    done
}

이제 get_crtime원하는만큼 파일 또는 디렉토리의 작성 날짜를 인쇄 할 수 있습니다 .

$ get_crtime foo foo/file 
foo Wed May 21 17:11:08 2014
foo/file    Wed May 21 17:11:27 2014

(이 같은 파일이 사본 인 경우 생성 날짜는 원본 파일의 생성 날짜가 아닙니다 입니다 수정 날짜). 파일이 복사되면 수정 날짜는 원본에서 나온 것이지만 작성 날짜는 사본에서 나온 것입니다. (이 질문에는 약간의 오해가 있습니다 : askubuntu.com/questions/529885/… )
Jacob Vlijm

1
@JacobVlijm 물론입니다. 분명하지 않습니까? 그렇지 않으면 어떻게 될 수 있습니까? 사본은 다른 파일과 동일한 내용을 갖는 새로운 파일입니다. 그런데 사본의 수정 시간도 변경됩니다. 사용하지 cp -p않거나 이와 유사한 것을 명시 적으로 선택하지 않는 한 복사본이 생성 된 순간으로 설정됩니다 .
terdon

물론, 그러나 동시에, 그것은 mod와 같이 비논리적이지 않을 것입니다. 날짜, 파일 어딘가에 날짜가 시작될 때 저장됩니다. 나는 연결된 질문에 대답하기 전까지는 그렇지 않다는 것을 인정해야한다.
Jacob Vlijm

방금 시도한 결과, 노틸러스로 파일을 복사하면 수정 날짜가 그대로 유지됩니다. 날짜가 작성 날짜보다 빠릅니다.
Jacob Vlijm

1
@demongolem 예, CentOS 버전은 옵션 df을 지원하지 않는 것 같습니다 --output. 이 경우 해당 줄을 바꿀 수 fs=$(df foo | awk '{a=$1}END{print a}'있으며 기능도 작동합니다. 이 답변에서 내가 보여주는 것은 파일 / 디렉토리 대상에 대해 직접 실행될 수있는 방식으로 허용 된 답변에서 명령을 래핑하는 방법입니다.
terdon

11

stat작성 시간을 표시 할 수없는 것은 stat(2)시스템 호출의 제한으로 인해 리턴 구조에 작성 시간에 대한 필드가 포함되지 않은 것입니다. 그러나 Linux 4.11 (17.10 이상 *)부터는 새로운 statx(2)시스템 호출 을 사용할 수 있습니다.이 시스템 호출 에는 반환 구조체에 생성 시간이 포함됩니다.

HWE (Hardware Enablement Stack) 커널을 사용하는 이전 LTS 릴리스에서도 가능합니다. 확인 uname -r당신이 적어도 4.11에서 확인하는 커널을 사용하고 있는지.

불행히도 C 프로그램에서 직접 시스템 호출을 호출하는 것은 쉽지 않습니다. 일반적으로 glibc는 작업을 쉽게하는 래퍼를 제공하지만, glibc statx(2)는 2018 년 8 월 (버전 2.28 , 18.10에서 사용 가능) 에만 래퍼를 추가했습니다 . 다행히 @whotwagner는 x86 및 x86-64 시스템 에서 시스템 호출 을 사용하는 방법을 보여주는 샘플 C 프로그램 을 작성 했습니다statx(2) . 출력 stat옵션은 서식 옵션없이 기본값 과 동일한 형식 이지만 출생 시간 만 인쇄하도록 수정하는 것은 간단합니다.

먼저 복제하십시오.

git clone https://github.com/whotwagner/statx-fun

statx.c코드 를 컴파일 하거나 출생 시간을 원하는 경우 birth.c다음 코드를 사용하여 복제 된 디렉토리에를 생성 할 수 있습니다 ( statx.c나노초 정밀도를 포함하여 생성 타임 스탬프 만 인쇄 하는 최소 버전 ).

#define _GNU_SOURCE
#define _ATFILE_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include "statx.h"
#include <time.h>
#include <getopt.h>
#include <string.h>

// does not (yet) provide a wrapper for the statx() system call
#include <sys/syscall.h>

/* this code works ony with x86 and x86_64 */
#if __x86_64__
#define __NR_statx 332
#else
#define __NR_statx 383
#endif

#define statx(a,b,c,d,e) syscall(__NR_statx,(a),(b),(c),(d),(e))

int main(int argc, char *argv[])
{
    int dirfd = AT_FDCWD;
    int flags = AT_SYMLINK_NOFOLLOW;
    unsigned int mask = STATX_ALL;
    struct statx stxbuf;
    long ret = 0;

    int opt = 0;

    while(( opt = getopt(argc, argv, "alfd")) != -1)
    {
        switch(opt) {
            case 'a':
                flags |= AT_NO_AUTOMOUNT;
                break;
            case 'l':
                flags &= ~AT_SYMLINK_NOFOLLOW;
                break;
            case 'f':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_FORCE_SYNC;
                break;
            case 'd':
                flags &= ~AT_STATX_SYNC_TYPE;
                flags |= AT_STATX_DONT_SYNC;
                break;
            default:
                exit(EXIT_SUCCESS);
                break;
        }
    }

    if (optind >= argc) {
        exit(EXIT_FAILURE);
    }

    for (; optind < argc; optind++) {
        memset(&stxbuf, 0xbf, sizeof(stxbuf));
        ret = statx(dirfd, argv[optind], flags, mask, &stxbuf);
        if( ret < 0)
        {
            perror("statx");
            return EXIT_FAILURE;
        }
        printf("%lld.%u\n", *&stxbuf.stx_btime.tv_sec, *&stxbuf.stx_btime.tv_nsec);
    }
    return EXIT_SUCCESS;
}

그때:

$ make birth
$ ./birth ./birth.c
1511793291.254337149
$ ./birth ./birth.c | xargs -I {} date -d @{}
Mon Nov 27 14:34:51 UTC 2017

이론적으로는 생성 시간을보다 쉽게 ​​이용할 수 있도록해야합니다.

  • ext * 파일보다 더 많은 파일 시스템을 지원해야합니다 ( debugfsext2 / 3 / 4 파일 시스템을위한 도구이며 다른 시스템에서는 사용할 수 없음)
  • 이것을 사용하기 위해 루트가 필요하지 않습니다 ( make및 같은 필수 패키지 설치 제외 linux-libc-dev).

예를 들어 xfs 시스템 테스트 :

$ truncate -s 1G temp; mkfs -t xfs temp; mkdir foo; sudo mount temp foo; sudo chown $USER foo
$ touch foo/bar
$ # some time later
$ echo > foo/bar
$ chmod og-w foo/bar
$ ./birth foo/bar | xargs -I {} date -d @{}
Mon Nov 27 14:43:21 UTC 2017
$ stat foo/bar                             
  File: foo/bar
  Size: 1           Blocks: 8          IO Block: 4096   regular file
Device: 700h/1792d  Inode: 99          Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/ muru)      Gid: ( 1000/ muru)
Access: 2017-11-27 14:43:32.845579010 +0000
Modify: 2017-11-27 14:44:38.809696644 +0000
Change: 2017-11-27 14:44:45.536112317 +0000
 Birth: -

그러나 이것은 NTFS 및 exfat에서는 작동하지 않았습니다. 나는 그것들을위한 FUSE 파일 시스템이 생성 시간을 포함하지 않았다고 생각한다.


만약 glibc가 statx(2)시스템 호출에 대한 지원을 추가한다면, stat곧 따라 올 것이며 우리는 stat이것을 위해 일반 명령 을 사용할 수있을 것 입니다. 그러나 나는 이것이 새로운 커널을 얻더라도 LTS 릴리스로 백 포트 될 것이라고 생각하지 않습니다. 그래서, 나는 기대하지 않습니다 stat있는 현재 LTS 릴리스 지금까지 수동 개입없이 생성 시간을 인쇄 (14.04, 16.04 또는 18.04).

그러나 18.10에서는 statx설명 된대로 함수를 직접 사용할 수 있습니다 man 2 statx(glibc가 래퍼를 아직 추가하지 않았다는 18.10 맨 페이지는 올바르지 않습니다).


github에 연결해 주셔서 감사합니다. 몇 달 전에 4.11이 나왔을 때 아무것도 찾지 못하고 잊어 버렸을 때 검색했습니다.
WinEunuuchs2Unix

@ WinEunuuchs2unix 핑으로 용서하지만 muru의 계정이 왜 rep의 메타 사이트인지 물어 보는 것이 1좋을까요?
George Udosen

@GeorgeUdosen 충격적입니다! 내가 왜하지만 직감을 가지고 ...
WinEunuuchs2Unix

@GeorgeUdosen 일반적으로 정지에 대한 최근 메타 질문이 있으며 특정 사용자를 대상으로하지 않습니다 : meta.askubuntu.com/questions/18341/… 대화방에 들어가서 대화를 계속할 수 있습니다. 소원.
WinEunuuchs2Unix

이제 기능을 사용할 수 있으므로 해당 필드를 수정하는 방법을 알고 있습니까? 파이썬에서 ctypes 래퍼를 만들려고 할 수 있습니다. 감사.
Gringo Suave

3

TL; DR : 그냥 실행 : sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

(실행하십시오 FS를 파악하려면 df -T /path/to/your/file이 될 것 가능성, /dev/sda1).

긴 버전 :

우리는 두 가지 명령을 실행할 것입니다.

  1. 파일의 파티션 이름을 찾으십시오.

    df -T /path/to/your/file

    결과는 다음과 같습니다 (파티션 이름이 첫 번째 임).

    Filesystem     Type 1K-blocks    Used Available Use% Mounted on
    /dev/<your fs> ext4   7251432 3481272   3509836  50% /
    
  2. 해당 파일의 작성 시간을 찾으십시오.

    sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>
    

    출력에서을 찾으십시오 ctime.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.