Linux get file modify time

File modification time (seconds) on Unix

On Unix, is there a command to display a file’s modification time, precise to the second? On Linux this is easily done with a «stat -c %y», which returns something like 2009-11-27 11:36:06.000000000 +0100 . I found no equivalent on Unix.

Ok, so if I write a program which uses an API call with parameters it’s ok to ask here. But if I write a program which calls another program with parameters it’s not? Is that what you’re saying?

12 Answers 12

Which exports something like this:

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 

Worked fine on SmartOS, which is shipped with a GNU ls. So if you need it on Solaris, you should be able to get the same result by using the GNU version of ls.

Prints — — ls: illegal option — — ls: illegal option — y ls: illegal option — = ls: illegal option — + ls: illegal option — % ls: illegal option — — ls: illegal option — % ls: illegal option — — ls: illegal option — % ls: illegal option — Y ls: illegal option — ls: illegal option — % ls: illegal option — : ls: illegal option — % ls: illegal option — M ls: illegal option — : ls: illegal option — %

According to the man page on my Mac (which has the BSD standard version of stat) you can get the epoch time version of the modification in seconds with:

Or if you want to print that out in hours:mins:secs you can do this:

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

Most Unix flavors have BSD style commands (of which stat is one) Linux has GNU style commands (which has a stat with different switches). If your Unix flavor doesn’t have stat at all you’d better tell us which Unix you’re using.

perl has a lstat() function, no need to call the stat utility from there. (lstat(«file»))[9] for the mtime. To format the date with BSD stat : stat -t ‘%F %T %z’ -f %Sm file

The following gives you last modified time in seconds since Epoch:

That’s specific to the GNU implementation of stat . Other stat implementations include (in chronological order): IRIX stat, zsh stat builtin, BSD stat.

The find command is a good source for all kinds of file information, including modification time to the second:

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

The first argument can be a file. The maxdepth prevents searching if a directory name is given. The %T instructs it to print last modification time.

Some systems interpret %TS as a floating point seconds (e.g. 36.8342610). If you want fractional seconds use «%TS» instead of «%.2TS», but you may not see fractional seconds on every system.

One up-vote for a good idea. One down-vote for not considering the question was about a command in Unix. The printf option isn’t available in find on Solaris or MacOS because as @StephaneChazelas says it’s GNU-specific.

For anyone facing the same issue, I found no solution (on HP-UX 11i anyway). Ended up coding a personalized «ls -lh» for my needs. It’s not that hard.. Prints something like :

 - 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 #include #include #include #include #include #include #include #include #include //#include #include // PATH_MAX #include #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[] = ; 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; > 

In printFSObjectInfo() you have full functionality of lstat() system call, you can customize this to your wishes.

Читайте также:  Linux ошибка проверки файловых систем

Источник

Get Last Modified Date of File in Linux

I’m new to Linux. I’m using the command-line. I’m trying to view the last modified date of a file. How do I do that in Linux from the Command Line?

@BrunoBieri It’s the modification date. See man ls . Typical Linux file systems don’t even track creation date — see the accepted answer for the kinds of dates kept track of.

7 Answers 7

As mentioned by @edvinas.me, stat tells you various information about the file including the last modified date.

At first, I was confused with Modify and Change, just to clarify, stat output lists:

  • Access shows the time of last data access (e.g. read).
  • Modify shows the time of last data modification.
  • Change shows the time the file status last changed.
~ $ touch foo ~ $ stat foo File: ‘foo’ Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: fc01h/64513d Inode: 410397 Links: 1 Access: (0644/-rw-r--r--) Uid: (80972/ etomort) Gid: (18429/ eem_tw) Access: 2015-09-21 12:06:11.343616258 +0200 Modify: 2015-09-21 12:06:11.343616258 +0200 Change: 2015-09-21 12:06:11.343616258 +0200 Birth: - ~ $ echo "Added bar to foo file" >> foo ~ $ stat foo File: ‘foo’ Size: 42 Blocks: 8 IO Block: 4096 regular file Device: fc01h/64513d Inode: 410654 Links: 1 Access: (0644/-rw-r--r--) Uid: (80972/ etomort) Gid: (18429/ eem_tw) Access: 2015-09-21 12:09:31.298712951 +0200 Modify: 2015-09-21 12:09:31.298712951 +0200 Change: 2015-09-21 12:09:31.302713093 +0200 Birth: - ~ $ chmod 444 foo ~ $ stat foo File: ‘foo’ Size: 42 Blocks: 8 IO Block: 4096 regular file Device: fc01h/64513d Inode: 410654 Links: 1 Access: (0444/-r--r--r--) Uid: (80972/ etomort) Gid: (18429/ eem_tw) Access: 2015-09-21 12:09:31.298712951 +0200 Modify: 2015-09-21 12:09:31.298712951 +0200 Change: 2015-09-21 12:10:16.040310543 +0200 Birth: - 

Use stat command for that:

Читайте также:  Поменять цвет командной строки линукс

Another way that is more flexible is using date -r . From man date :

-r, --reference=FILE display the last modification time of FILE 

This has the advantage of allowing you to specify the output format, e.g.

$ date -r foo Thu Aug 31 10:36:28 AEST 2017 $ date -r foo -R Thu, 31 Aug 2017 10:36:28 +1000 $ date -r foo -u Thu Aug 31 00:36:28 UTC 2017 $ date -r foo +%s 1504139788 

Yes, very helpful, thanks. Here is a bash function that will rename a file to be prefixed by the modified time: function mvfilestime() < if [ x"$<1>» = «x» ] ; then echo «mvfilestime: Missing argument of file to mv» else f=$(date +»%Y-%m-%d-%H-%M» -r $<1>)-$ <1>echo mv $ <1>$ mv $ <1>$ fi >

#> ls -l /home/TEST/ total 16 -rw-r--r-- 1 rfmas1 nms 949 Nov 16 12:21 create_nd_lists.py -rw-r--r-- 1 rfmas1 nms 0 Nov 16 12:35 enb_list -rw-r--r-- 1 rfmas1 nms 0 Nov 16 12:35 nb_list -rw-r--r-- 1 rfmas1 nms 0 Nov 16 12:35 nodes_ip.txt -rw-r--r-- 1 rfmas1 nms 0 Nov 16 12:35 rnc_list 

Building off of @Adam Taylor ‘s comment in @phoops ‘s answer and @Sparhawk ‘s answer.

To specifically just get the date (using October 3, 2019 for examples because it was my last birthday)

  • stat -c %y file | cut -d’ ‘ -f1 will give you 2019-10-03
  • date +%F -r file will also give you 2019-10-03
  • date +%D -r file will give you 10/03/19
  • date +%x -r file will probably give either 10/03/2019 , or 10/03/19 if you’re in the U.S. and either 03/10/2019 , or 03/10/19 if you’re in the U.K., just to name a couple examples (of course there are more possibilities)
Читайте также:  Linux mint opensuse ubuntu

These date format options are, to my understanding, combinations of other format options. Here are some explanations from the man page:

%b locale’s abbreviated month name (e.g., Jan)
%B locale’s full month name (e.g., January)
.
%d day of month (e.g, 01)
%D date; same as %m/%d/%y
%e day of month, space padded; same as %_d
%F full date; same as %Y-%m-%d
.
%m month (01..12)
.
%x locale’s date representation (e.g., 12/31/99)
.
%y last two digits of year (00..99)
%Y year
.
By default, date pads numeric fields with zeroes.
The following optional flags may follow `%’:

— (hyphen) do not pad the field
_ (underscore) pad with spaces
0 (zero) pad with zeros
^ use upper case if possible

use opposite case if possible

N.B.: These flags don’t work on the «combo formats» like %F , %D and %x . They are for the «singular field formats«.

Apparently this last flag (#) does not work as I’d expect (e.g., if date +%b gives Oct , date +%#b gives OCT as opposed to oCT ) I guess this would be useless, but I’d think a lower case option would be more useful. date +%#p does turn date +%p which might give PM or AM into pm or am , respectively. So I guess it’s not a ‘per-character’ case switch but sets the case of all the characters in the string to the opposite case of the majority of the characters? Also date +%P gives pm or am , but neither date +%^P nor date +%#P change its output. My guess for this case is that %P is just an alias for %#p , and it seems that whenever you add more than one flag, the behavior is undefined/unpredictable ( e.g., date +%0-e gives the same as date +%-e : 3 and date +%-0e gives the same as date +%0e : 03 , which makes you think that only the flag next to the letter works or that it goes left to right, but both date +%#^p and date +%^#p give pm or am , [depending on the time of course] ) unless there’s some hidden order of operations? Sorry for digressing.

Also, if you run the command locale -k LC_TIME | grep ^d_fmt , you can see the combo for the specific locale of your system (e.g., d_fmt=»%m/%d/%Y» ).

And you can make your own combo. For example,

Источник

Оцените статью
Adblock
detector