【问题标题】:File modification time (seconds) on UnixUnix 上的文件修改时间(秒)
【发布时间】:2018-05-21 00:22:22
【问题描述】:

在 Unix 上,是否有显示文件修改时间的命令,精确到秒?

在 Linux 上,这很容易通过“stat -c %y”来完成,它返回类似2009-11-27 11:36:06.000000000 +0100 的内容。我在 Unix 上没有找到对应的。

【问题讨论】:

  • 这显然是出于脚本开发目的,在我看来这意味着它显然属于这里。
  • 我使用桌椅进行开发,这也算吗?
  • 好的,所以如果我编写的程序使用带参数的 API 调用,可以在这里询问。但是,如果我编写一个程序调用另一个带有参数的程序,那不是吗?你说的是这个吗?

标签: unix file time


【解决方案1】:

我发现了这个:

ls --time-style='+%d-%m-%Y %H:%M:%S' -l

导出类似这样的内容:

root:~# ls --time-style='+%d-%m-%Y %H:%M:%S' -l
total 0
-rw-r--r-- 1 root root 0 16-04-2015 23:14:02 other-file.txt
-rw-r--r-- 1 root root 0 16-04-2015 23:13:58 test.txt

【讨论】:

  • 不错的发现!在 Solaris 中不起作用。可能只有 Linux。
  • 在 SmartOS 上运行良好,它附带 GNU ls。因此,如果您在 Solaris 上需要它,您应该能够通过使用 GNU 版本的 ls 获得相同的结果。
  • 这是特定于ls 的 GNU 实现的。 FreeBSD ls 有一个 -D 选项。
  • OS X 10.11 中内置的ls 似乎没有任何用于此目的的选项。
  • 打印 -- - ls: 非法选项 -- - ls: 非法选项 -- y ls: 非法选项 --= ls: 非法选项 -- + ls: 非法选项 -- % ls: 非法选项 -- - ls: 非法选项 -- % ls: 非法选项 -- - ls: 非法选项 -- % ls: 非法选项 -- Y ls: 非法选项 -- ls: 非法选项 -- % ls: 非法选项 - - : ls: 非法选项 -- % ls: 非法选项 -- M ls: 非法选项 -- : ls: 非法选项 -- %
【解决方案2】:

根据我的 Mac 上的手册页(具有 BSD 标准版本的 stat),您可以在几秒钟内获得修改的纪元时间版本:

stat -f %m /etc/passwd

或者,如果您想在小时:分钟:秒内打印出来,您可以这样做:

perl -e "print scalar(localtime(`stat -f %m /etc/passwd`))"

【讨论】:

  • 大多数 Unix 风格都有 BSD 风格的命令(其中 stat 是其中之一) Linux 有 GNU 风格的命令(它有一个带有不同开关的 stat)。如果您的 Unix 风格根本没有统计信息,最好告诉我们您使用的是哪个 Unix。
  • perl 有一个lstat() 函数,无需从那里调用stat 实用程序。 (lstat("file"))[9] 为 mtime。用 BSD stat 格式化日期:stat -t '%F %T %z' -f %Sm file
【解决方案3】:

以下内容为您提供自 Epoch 以来的最后修改时间(以秒为单位):

stat -c%Y <file>

【讨论】:

  • 这是特定于stat 的 GNU 实现的。其他stat 实现包括(按时间顺序):IRIX stat、zsh stat builtin、BSD stat。
【解决方案4】:

find命令是各种文件信息的好来源,包括修改时间到秒:

find /etc/passwd -maxdepth 0 -printf "%TY/%Tm/%Td %TH:%TM:%.2TS\n"
2011/11/21 13:41:36

第一个参数可以是一个文件。如果给出了目录名称,则 maxdepth 会阻止搜索。 %T 指示它打印上次修改时间。

某些系统将 %TS 解释为浮点秒数(例如 36.8342610)。如果您想要小数秒,请使用“%TS”而不是“%.2TS”,但您可能不会在每个系统上看到小数秒。

【讨论】:

  • 这是特定于find 的 GNU 实现的。
  • 发现:缺少连词
  • 一个好主意投赞成票。一个不考虑这个问题的反对票是关于 Unix 中的一个命令。 printf 选项在 Solaris 或 MacOS 上的 find 中不可用,因为 @StephaneChazelas 说它是 GNU 特定的。
【解决方案5】:

对于面临相同问题的任何人,我都没有找到解决方案(无论如何在 HP-UX 11i 上)。 最后根据我的需要编写了一个个性化的“ls -lh”。没那么难。。 打印类似:

 - 664 rw-/rw-/r--   1L expertNoob adm   8.37 kB 2010.08.24 12:11:15 findf1.c
 d 775 rwx/rwx/r-x   2L expertNoob adm     96 B  2010.08.24 15:17:37 tmp/
 - 775 rwx/rwx/r-x   1L expertNoob adm     16 kB 2010.08.24 12:35:30 findf1
 - 775 rwx/rwx/r-x   1L expertNoob adm     24 kB 2010.09.14 19:45:20 dir_info
 - 444 r--/r--/r--   1L expertNoob adm   9.01 kB 2010.09.01 11:23:41 getopt.c
 - 664 rw-/rw-/r--   1L expertNoob adm   6.86 kB 2010.09.01 11:24:47 getopt.o
 - 664 rw-/rw-/r--   1L expertNoob adm   6.93 kB 2010.09.14 19:37:44 findf1.o
 l 775 rwx/rwx/r-x   1L expertNoob adm      6 B  2010.10.06 17:09:01 test1 -> test.c
 - 664 rw-/rw-/r--   1L expertNoob adm    534 B  2009.03.26 15:34:23 > test.c
 d 755 rwx/r-x/r-x  25L expertNoob adm      8 kB 2009.05.20 15:36:23 zip30/

这里是:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <locale.h>
#include <langinfo.h>
#include <stdio.h>
//#include <stdint.h>
#include <limits.h> // PATH_MAX
#include <stdarg.h>
#include "getopt.h"

static short START_VSNBUFF=16;
// This is bformat from Better String library (bstrlib), customized
int strformat (char ** str, const char * fmt, ...) {

    va_list arglist;
    char * buff;
    int n, r;

    /* Since the length is not determinable beforehand, a search is
       performed using the truncating "vsnprintf" call (to avoid buffer
       overflows) on increasing potential sizes for the output result. */

    if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF;
    if ( NULL == ( buff = (char *) malloc((n + 2)*sizeof(char)) ) ) {
        n = 1;
        if ( NULL == ( buff = (char *) malloc((n + 2)*sizeof(char)) ) ) {
            fprintf( stderr, "strformat: not enough memory to format string\n" );
            return -1;
        }
    }

    for (;;) {
        va_start (arglist, fmt);
        r = vsnprintf (buff, n + 1, fmt, arglist); // n+1 chars: buff[0]..buff[n], n chars from arglist: buff[n]='\0'
        va_end (arglist);

        buff[n] = (unsigned char) '\0'; // doesn't hurt, especially strlen!

        if ( strlen(buff) < n ) break;

        if (r > n) n = r; else n += n;

        if ( NULL == ( buff = (char *) realloc( buff, (n + 2)*sizeof(char) ) ) ) {
            free(buff);
            fprintf( stderr, "strformat: not enough memory to format string\n" );
            return -1;
        }
    }

    if( NULL != *str ) free(*str);
    *str = buff;
    return 0;
}

int printFSObjectInfo( const char * path, const char * name ) {

    struct stat    statbuf;

    struct passwd *pwd;
    struct group  *grp;
    struct tm     *tm;
    char           datestring[256];
    char           *type = "? ";
    char           *fbuf = NULL;

    double         size = 0;
    const char     *units[] = {"B ", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
    int            i = 0;

    char owner[] = "---", group[] = "---", others[] = "---";


    /* Get entry's information. */
    if ( -1 == lstat( path, &statbuf ) ) {
        fprintf( stderr, "printFSObjectInfo: error: can't stat %s\n", path );
        if( 0 == strformat( &fbuf, "lstat() said: %s", path ) ) { perror(fbuf); return -1; }
    }

    // File type
    if( S_ISREG(statbuf.st_mode) ) type = "-"; // regular file
    if( S_ISDIR(statbuf.st_mode) ) {         // directory
        type="d";
        if( S_ISCDF(statbuf.st_mode) ) type = "hd";  // hidden dir
    }
    if( S_ISBLK(statbuf.st_mode) ) type = "b"; // block special
    if( S_ISCHR(statbuf.st_mode) ) type = "c"; // character special
    if( S_ISFIFO(statbuf.st_mode) ) type = "f"; // pipe or FIFO
    if( S_ISLNK(statbuf.st_mode) ) type = "l"; // symbolic link
    if( S_ISSOCK(statbuf.st_mode) ) type = "s"; // socket
    if( S_ISNWK(statbuf.st_mode) ) type = "n"; // network special
    printf( "%2s ", type );

    /* Print out type, permissions, and number of links. */
    //printf("%10.10s", sperm (statbuf.st_mode));
    if( S_IRUSR & statbuf.st_mode ) owner[0] = 'r';
    if( S_IWUSR & statbuf.st_mode ) owner[1] = 'w';
    if( S_IXUSR & statbuf.st_mode ) owner[2] = 'x';

    if( S_IRGRP & statbuf.st_mode ) group[0] = 'r';
    if( S_IWGRP & statbuf.st_mode ) group[1] = 'w';
    if( S_IXGRP & statbuf.st_mode ) group[2] = 'x';

    if( S_IROTH & statbuf.st_mode ) others[0] = 'r';
    if( S_IWOTH & statbuf.st_mode ) others[1] = 'w';
    if( S_IXOTH & statbuf.st_mode ) others[2] = 'x';

    //printf( "\n%o\n", statbuf.st_mode );
    printf( "%3o %s/%s/%s ", 0777 & statbuf.st_mode, owner, group, others );

    printf("%4dL", statbuf.st_nlink);

    /* Print out owner's name if it is found using getpwuid(). */
    if ((pwd = getpwuid(statbuf.st_uid)) != NULL)
        printf(" %-8.8s", pwd->pw_name);
    else
        printf(" %-8d", statbuf.st_uid);

    /* Print out group name if it is found using getgrgid(). */
    if ((grp = getgrgid(statbuf.st_gid)) != NULL)
        printf(" %-8.8s", grp->gr_name);
    else
        printf(" %-8d", statbuf.st_gid);

    /* Print size of file. */
    //printf(" %9d", (int)statbuf.st_size);
    i = 0;
    size = (double) statbuf.st_size;
    while (size >= 1024) {
        size /= 1024;
        i++;
    }
    if( 0 == (double)(size - (long) size) )
         printf( "%7d %-2s",  (long)size, units[i] );
    else printf( "%7.2f %-2s", size, units[i] );

    tm = localtime(&statbuf.st_mtime);

    /* Get localized date string. */
    strftime(datestring, sizeof(datestring), "%Y.%m.%d %T", tm); // nl_langinfo(D_T_FMT)

    if ( 0 == strcmp(name, "\n") )
         printf(" %s > %s", datestring, path);
    else {
        if( 0 == strcmp(type, "d") ) printf(" %s %s/", datestring, name);
        else                         printf(" %s %s", datestring, name);
    }

    if( 0 == strcmp(type, "l") ) {
        char buf[1+PATH_MAX];
        if( -1 == readlink( path, buf, (1+PATH_MAX) ) ) {
            fprintf( stderr, "printFSObjectInfo: error: can't read symbolic link %s\n", path);
            if( 0 == strformat( &fbuf, "readlink() said: %s:", path ) ) { perror(fbuf); return -2; }
        }
        else {
            lstat( buf, &statbuf ); // want errno, a symlink may point to non-existing object
            if(errno == ENOENT) printf(" -> %s [!no such file!]\n", buf );
            else {
                printf(" -> %s\n", buf );
                if ( 0 != strcmp(name, "\n") ) printFSObjectInfo( buf, "\n" );
            }
        }
    }
    else printf("\n");

    return 0;
}

int main(int argc, char **argv) {

    struct dirent *dp;
    struct stat    statbuf;

    char           *path = NULL; //[1+PATH_MAX];
    char           *fbuf = NULL;
    char           *pathArg = NULL;

    if( argc == 1 || 0 == strlen(argv[1]) ) pathArg = ".";
    else pathArg = argv[1];

    if ( lstat( pathArg, &statbuf ) == -1 ) {
        printf("%s: error: can't stat %s\n", argv[0], pathArg);
        if( 0 == strformat( &fbuf, "stat() said: %s", pathArg ) ) perror(fbuf);
        exit(2);
    }

if( S_ISDIR(statbuf.st_mode) ) {
    DIR *dir = opendir( pathArg );
    if( NULL == dir ) {
        fprintf( stderr, "%s: error: can't open %s\n", argv[0], pathArg );
        if( 0 != strformat( &fbuf, "opendir() said: %s", pathArg ) ) exit(5);
        perror(fbuf);
        exit(4);
    }

    /* Loop through directory entries. */
    while ( (dp = readdir(dir)) != NULL ) {

        if( 0!= strformat( &path, "%s/%s", pathArg, dp->d_name ) ) continue;

        printFSObjectInfo( path, dp->d_name );
    }
    closedir(dir);
} else  printFSObjectInfo( pathArg, pathArg );

    return 0;
}

在 printFSObjectInfo() 中,您拥有 lstat() 系统调用的全部功能,您可以根据自己的意愿对其进行自定义。

好好的。

【讨论】:

    【解决方案6】:

    尝试使用 perl 单行:

    perl -e '@d=localtime ((stat(shift))[9]); printf "%02d-%02d-%04d %02d:%02d:%02d\n", $d[3],$d[4]+1,$d[5]+1900,$d[2],$d[1],$d[0]' your_file_to_show_the_date_for.your_extension
    

    【讨论】:

      【解决方案7】:

      ls -le 如果您只需要 HH:MM:SS

      就可以使用

      【讨论】:

        【解决方案8】:

        在 Mac OS X 上(在 10.10.5 Yosemite 至 10.12.4 Sierra 上测试):

        prompt> ls -lT
        
        total 0
        -rw-r--r--  1 youruser  staff  0 Sep 24 10:28:30 2015 my_file_1.txt
        -rw-r--r--  1 youruser  staff  0 Sep 24 10:28:35 2015 my_file_2.txt
        

        【讨论】:

          【解决方案9】:

          如果您使用的是 HP-UX:

          好吧,假设文件的名称是“垃圾”。在 HP-UX 上,您可以:

          perl -e '@d=localtime ((stat(shift))[9]); printf "%4d-%02d-%02d %02d:%02d:%02d\n", $d[5]+1900,$d[4]+1,$d[3],$d[2], $d[1],$d[0]' 垃圾

          是的,perl 随 HP-UX 一起提供。它在 /usr/contrib 中。但您可能在 /usr/local 或 /opt 中有更新的版本。

          来源:Perderabo

          【讨论】:

            【解决方案10】:

            今天我在旧版本的 HP-UX 上遇到了同样的问题。 stat 程序不是安装的一部分。 (只是 C 版本)

            对我来说最快的解决方案是使用在我的笔记本电脑上运行的诸如 Tectia 文件传输之类的工具,而无需实际进行任何复制,它会为您从 HP-UX 转换上次修改的时间,并提供所有文件的日期和时间登录 UNIX 后。

            这可能适用于其他类似的基于图形的文件传输工具,但我还没有尝试过。

            【讨论】:

              【解决方案11】:

              在 AIX 上,istat 命令执行此操作:

              machine:~/support> istat ../core 
              Inode 30034 on device 32/3      File
              Protection: rw-rw-r--   
              Owner: 500(group)             Group: 500(user)
              Link count:   1         Length 10787748 bytes
              
              Last updated:   Wed Feb 22 13:54:28 2012
              Last modified:  Wed Feb 22 13:54:28 2012
              Last accessed:  Wed Feb 22 19:58:10 2012
              

              【讨论】:

                【解决方案12】:

                秒:

                date +%s -r /etc/passwd
                

                或者,如果您的文件系统支持,则精度更高(最高可达纳秒级):

                date +%s.%N -r /etc/passwd
                

                【讨论】:

                  猜你喜欢
                  • 2013-10-21
                  • 1970-01-01
                  • 2011-04-30
                  • 2011-02-24
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多