Bir dosyanın oluşturulma süresini nasıl bulabilirim?


64

Bir dosyanın yaratılma zamanını bulmam gerekiyor, bu konuyla ilgili bazı makaleler okuduğumda, hepsi çözüm bulunmadığını ( Site1 , Site2 gibi ) bahsetti .

statKomutu denediğimde, belirtiyor Birth: -.

Peki bir dosyanın oluşturulma zamanını nasıl bulabilirim?


2
Bir dosyanın 'yaratma zamanının' doğru olacağının garanti edilmediğini unutmayın. Bir dosyadaki oluşturma tarihlerini "fudge" etmenin birçok yolu vardır.
Thomas Ward,

1
@ThomasWard Diğer dosya verilerini doldurmanın bir çok yolu var mı?
Cees Timmerman

Yanıtlar:


67

Bir dizinin yaratılma tarihini bilmenin bir yolu var, sadece şu adımları izleyin:

  1. Bilin düğüm tarafından dizinin ls -ikomuta (örneğin onun için diyelim X )

  2. Dizininizin hangi bölüme df -T /pathkomut tarafından kaydedildiğini bilin (diyelim /dev/sda1)

  3. Şimdi bu komutu kullanın: sudo debugfs -R 'stat <X>' /dev/sda1

Çıktıda göreceksiniz:

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

crtime , dosyanızın oluşturulma tarihidir.

Ne test ettim :

  1. Belirli bir zamanda bir dizin oluşturuldu.
  2. Erişildi.
  3. Bir dosya oluşturarak değiştirildi.

  4. Komutu denedim ve kesin bir zaman verdi.

  5. Sonra değiştiririm ve tekrar test ederim , crtime aynı kaldı, ancak değiştirme ve erişim zamanı değişti.

Bunu yazıyorum, çünkü daha iyi anlayabilmeyi tartışmaktan hoşlanıyorum, insanların neden Linux'un bu özelliği desteklemediğini söylediklerini merak ediyorum
nux

13
Çünkü Linux kendisi değil. Ext4 dosya sistemi bu bilgilere sahiptir, ancak çekirdek ona erişmek için bir API sağlamamaktadır. Görünüşe göre, debugfsonu doğrudan dosya sisteminden ayıklar , böylece çekirdeğin API'sini kullanmasına gerek kalmaz. Buraya bakınız .
terdon

Test ettim. Ext4 dosya sisteminde mükemmel çalıştı
Fahim Babar Patel

1
Bu ext4'e özgü mü görünüyor? Benim için XFS ile çalışmadı.
Quantum7

Çekirdek, glibc ve coreutils şimdi statx()Mart 2019'dan itibaren destek
hippietrail

54

@Nux , hepinizin oy kullanması gereken harika bir çözüm buldu . Her şeyi doğrudan çalıştırmak için kullanılabilecek küçük bir fonksiyon yazmaya karar verdim. Bunu da ekle ~/.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
}

Artık istediğiniz get_crtimesayıda dosya veya dizinin oluşturulma tarihini basmak için koşabilirsiniz :

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

Oluşturma tarihinin, dosyanın bir kopyası olması durumunda ( değişiklik tarihi ile olduğu gibi), orijinal dosyanın oluşturulma tarihi olmadığını unutmayın . Bir dosya kopyalandıktan sonra, değişiklik tarihi orijinaldir, ancak oluşturma tarihi kopyadan alınır. (bu sorudaki bazı yanlış anlamalar var: askubuntu.com/questions/529885/… )
Jacob Vlijm

1
@JocobVlijm elbette, evet, evet. Bu açık değil mi? Aksi nasıl olabilir? Bir kopya, başka bir içerikle aynı olan yeni bir dosyadır. Değiştirme zamanı ayrıca bir kopya için bu arada da değişir. Kullanımın cp -pveya benzeri bir şey olmamasını açıkça seçmemeniz durumunda, kopya oluşturulduğu an ayarlanır .
terdon

Kesinlikle, ama aynı zamanda, mod gibi olsaydı, o kadar da mantıksız olmazdı. tarih, dosyanın herhangi bir yerinde, o tarih geldiğinde saklanacak olan tarih. İtiraf etmeliyim ki, bağlantılı soruyu cevaplayana kadar durum böyle değildi.
Jacob Vlijm

Sadece bu arada denedim, sadece nautilus'ta dosya kopyaladım, değişiklik tarihi olduğu gibi kalıyor, m. tarih oluşturma tarihinden önce.
Jacob Vlijm

1
@demongolem evet, CentOS sürümü seçeneği dfdesteklemiyor gibi görünüyor --output. Bu durumda, bu çizgiyi değiştirebilir fs=$(df foo | awk '{a=$1}END{print a}'ve işlev de çalışır. Bu cevapta gösterdiğim tek şey, komutu kabul edilen cevaptan doğrudan dosya / dizin hedefleri için çalıştırılabilecek şekilde sarmanın bir yoludur.
terdon

11

Yetersizlik statyaratma zamanı göstermek için bir sınırlama kaynaklanmaktadır stat(2)sistem çağrısı dönüş yapı oluşturma zaman için bir alan içermiyordu. Bununla birlikte, Linux 4.11'den başlayarak (yani, 17.10 ve daha yeni *), ancak geri dönüş yapısında bir oluşturma zamanı içeren yeni statx(2)sistem çağrısı kullanılabilir.

* Büyük olasılıkla daha eski LTS sürümlerinde donanım etkinleştirme yığını (HWE) çekirdeklerini kullanarak. uname -rOnaylamak için en az 4.11'de bir çekirdek kullanıp kullanmadığınızı kontrol edin .

Ne yazık ki, sistem çağrılarını doğrudan bir C programında çağırmak kolay değildir. Genellikle glibc, işi kolaylaştıran bir sarıcı sağlar, ancak glibc yalnızca statx(2)Ağustos 2018'deki bir sarıcıyı ekler (sürüm 2.28 , 18.10'da bulunur). Neyse ki, @whotwagner , x86 ve x86-64 sistemlerinde sistem çağrısının nasıl kullanılacağını gösteren örnek bir C programı yazdı statx(2). Çıktı stat, herhangi bir biçimlendirme seçeneği olmadan varsayılanla aynıdır , ancak yalnızca doğum zamanını yazdırmak için değiştirmek kolaydır.

İlk önce, onu kopyalayın:

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

statx.cKodu derleyebilir veya yalnızca doğum saatini istiyorsanız birth.c, aşağıdaki kodla klonlanmış bir dizinde bir dizin oluşturabilirsiniz (bu, statx.cnanosaniye kesinliği dahil yalnızca oluşturma zaman damgasının yazdırılmasının minimal bir sürümüdür ):

#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;
}

Sonra:

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

Teoride bu, yaratma zamanını daha erişilebilir hale getirmelidir:

  • ext * olanlardan daha fazla dosya sistemi desteklenmelidir ( debugfsext2 / 3/4 dosya sistemleri için bir araçtır ve diğerleri için kullanılamaz)
  • Bunu kullanmak için root kullanmanıza gerek yoktur ( makeve gibi bazı gerekli paketleri kurmak dışında linux-libc-dev).

Bir xfs sistemini test etmek, örneğin:

$ 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: -

Ancak, bu NTFS ve exfat için işe yaramadı. Sanırım bunlar için FUSE dosya sistemleri oluşturma zamanını içermiyordu.


Eğer, ya da daha doğrusu, glibc statx(2)sistem çağrısı için destek eklerse , statyakında takip eder ve bunun için düz eski statkomutu kullanabiliriz . Ancak bunun, daha yeni çekirdek alsalar bile, LTS sürümlerine destekleneceğini sanmıyorum. Yani, beklemeyin statüzerinde herhangi bir geçerli LTS sürümü şimdiye manuel müdahale olmadan oluşturma süresini yazdırmak için (14.04, 16.04 veya 18.04).

Bununla birlikte, 18.10'da, statxişlevi açıklandığı şekilde doğrudan kullanabilirsiniz man 2 statx(18.10 kılavuz sayfasının, glibc'nin henüz sarıcıyı eklemediğini belirtmekte yanlış olduğunu unutmayın).


Github ile bağlantı kurduğunuz için teşekkür ederiz. Birkaç ay önce 4.11 gelip bir şey bulamadığımda aradım ve unuttum.
WinEunuuchs2Unix

@ WinEunuuchs2unix pingle affet ama meta sitede neden muru'nun hesabının haklı bir temsilcisi olduğunu sormak akıllıca olur 1mu?
George Udosen

@GeorgeUdosen Şok edici! Neden olsa bir his var ...
WinEunuuchs2Unix

@GeorgeUdosen Genel olarak süspansiyonlarla ilgili son bir meta sorusu var ve belirli bir kullanıcıyı ele almıyorlar : meta.askubuntu.com/questions/18341/… Şimdi sohbet odasına gidiyorum, böylece konuşmaya devam edebilirsiniz. diliyorum.
WinEunuuchs2Unix

Şimdi bu özellik kullanılabilir durumda, bu alanı nasıl değiştireceğinizi biliyor musunuz? Python'da yapmak için bir ctypes sarmalayıcı oluşturmaya çalışabilirim. Teşekkürler.
Gringo Suave

3

TL; DR: Sadece koş: sudo debugfs -R 'stat /path/to/your/file' /dev/<your fs>

(Senin fs bulmak için, koşmak df -T /path/to/your/file, büyük olasılıkla olacak /dev/sda1).

Uzun versiyon:

İki komut uygulayacağız:

  1. Dosyanızın bölüm adının adını bulun.

    df -T /path/to/your/file

    Çıktı şöyle görünecek (bölüm adı önce):

    Filesystem     Type 1K-blocks    Used Available Use% Mounted on
    /dev/<your fs> ext4   7251432 3481272   3509836  50% /
    
  2. Bu dosyanın oluşturulma zamanını bulun.

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

    Çıktıda, arayın ctime.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.