Print a file’s last modified date in Bash
I can’t seem to find how to print out the date of a file. I’m so far able to print out all the files in a directory, but I need to print out the dates with it. I know I need to attach a date format with the echo of the entry, but all I can’t find the correct format.
echo "Please type in the directory you want all the files to be listed" read directory for entry in "$directory"/* do echo "$entry" done
10 Answers 10
Isn’t the ‘date’ command much simpler? No need for awk, stat, etc.
Also, consider looking at the man page for date formatting; for example with common date and time format:
It looks like BSD (or at least OS X’s) date ‘s doesn’t have this. Its -r is just used to provide a timestamp to format. You’ll have to use GNU date to get this functionality.
In macOS 10.13 date [-r seconds | filename] is fully documented in the man page, and works as expected.
%y time of last modification, human-readable
for entry in «$directory»/* do stat -c%y «$entry» done Doesn’t work. Prints out stat: missing operand in terminal
Note that on BSD the stat command has a different syntax. My case for FreeBSD: stat -f %Sm -t %F» «%R filename .
Alternatively, you may try also :
On OS X, I like my date to be in the format of YYYY-MM-DD HH:MM in the output for the file.
So to specify a file I would use:
stat -f "%Sm" -t "%Y-%m-%d %H:%M" [filename]
If I want to run it on a range of files, I can do something like this:
#!/usr/bin/env bash for i in /var/log/*.out; do stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i" done
This example will print out the last time I ran the sudo periodic daily weekly monthly command as it references the log files.
To add the filenames under each date, I would run the following instead:
#!/usr/bin/env bash for i in /var/log/*.out; do stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i" echo "$i" done
The output would was the following:
2016-40-01 16:40 /var/log/daily.out 2016-40-01 16:40 /var/log/monthly.out 2016-40-01 16:40 /var/log/weekly.out
Unfortunately I’m not sure how to prevent the line break and keep the file name appended to the end of the date without adding more lines to the script.
PS — I use #!/usr/bin/env bash as I’m a Python user by day, and have different versions of bash installed on my system instead of #!/bin/bash
In case you haven’t figured out the line break part, the -e flag is available for the echo program. Example usage could be: echo -e «$(stat -f %Sm -t %Y%m%d_%H%M%S $AFile)\t$AFile.» . In your case it could be: echo -e «$(stat -f «%Sm» -t «%Y-%m-%d %H:%M» «$i»)\t$i.» `
Adding to @StevePenny answer, you might want to cut the not-so-human-readable part:
stat -c%y Localizable.strings | cut -d'.' -f1
For the line breaks i edited your code to get something with no line breaks.
#!/bin/bash for i in /Users/anthonykiggundu/Sites/rku-it/*; do t=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$i") echo $t : "$" # t only contains date last modified, then only filename 'grokked'- else $i alone is abs. path done
If file name has no spaces:
This prints as the following format:
Dec 21 20:03 a1.out Dec 21 20:04 a.cpp
If file names have space (you can use the following command for file names with no spaces too, just it looks complicated/ugly than the former):
Ah, I see! That mostly works, except for the files with the spaces in the names. Is there a solution for that?
Actually, I tried it again, and it doesn’t work. turns out I was trying out a directory that had file names without spaces. =/ Edited my answer below
when you say it does not work, can you say what is the error? it works for me when i executed it on my system.
EDITED: turns out that I had forgotten the quotes needed for $entry in order to print correctly and not give the «no such file or directory» error. Thank you all so much for helping me!
echo "Please type in the directory you want all the files to be listed with last modified dates" #bash can't find file creation dates read directory for entry in "$directory"/* do modDate=$(stat -c %y "$entry") #%y = last modified. Qoutes are needed otherwise spaces in file name with give error of "no such file" modDate=$ #%% takes off everything off the string after the date to make it look pretty echo $entry:$modDate
/home/joanne/Dropbox/cheat sheet.docx:2012-03-14 /home/joanne/Dropbox/Comp:2013-05-05 /home/joanne/Dropbox/Comp 150 java.zip:2013-02-11 /home/joanne/Dropbox/Comp 151 Java 2.zip:2013-02-11 /home/joanne/Dropbox/Comp 162 Assembly Language.zip:2013-02-11 /home/joanne/Dropbox/Comp 262 Comp Architecture.zip:2012-12-12 /home/joanne/Dropbox/Comp 345 Image Processing.zip:2013-02-11 /home/joanne/Dropbox/Comp 362 Operating Systems:2013-05-05 /home/joanne/Dropbox/Comp 447 Societal Issues.zip:2013-02-11
How to check all timestamps of a file?
Is there a command in Linux to check all timestamps of a file? I’m trying to see the last modified, created, and touched dates on the file.
Just to point out, Linux files don’t have birth dates. Thus, it’s not possible to determine the date a file was created.
@FatalError: Various filesystems already support birth/creation timestamps; the real trouble is in accessing such extra information. (One can’t just extend struct stat without breaking things, unfortunately. ) You can try out debugfs -R «stat » /dev/sdXY for ext4, replacing 1234 with an ino.
@grawity: Neat! I always wondered why no fs had it. but I guess they do, but like you said, can’t just go breaking the ABI for existing binaries. Thanks for the tip :).
@FatalError, Birth time can be displayed with Linux stat command, see How to find creation date of file? and What file systems on Linux store the creation time?.
2 Answers 2
$ stat test 234881026 41570368 -rw-r--r-- 1 werner staff 0 0 "Feb 7 16:03:06 2012" "Feb 7 16:03:06 2012" "Feb 7 16:03:06 2012" "Feb 7 16:03:06 2012" 4096 0 0 test
If you want to adjust the format, refer to the man pages, since the output is OS-specific and varies under Linux/Unix.
Generally, you can get the times through a normal directory listing as well:
- ls -l outputs last time the file content was modified, the mtime
- ls -lc outputs last time of file status modification, the ctime (What’s the difference?)
- ls -lu outputs last access time, the atime (although the usefulness of this concept is subject to discussion)
And of course, ctime does not record when a file was «created». The POSIX specification defines only three timestamps, but some Linux filesystems store Birth Time/Creation Time. How to find creation date of file? On such a supported configuration, one could use
stat --printf '%n\nmtime: %y\nctime: %z\natime: %x\ncrtime:%w\n'
stat is really detailed. But ls only needs one line. It would be good if it could also display seconds. However, when creating lists of files, the former one is perfectly suitable.
I’ve noticed that the result of ls -l can show a different date format when there is BusyBox installed (on Android). I think that without it , it’s like «2019-07-26 14:41» , and with it, it’s like «May 6 21:27» . How come the year is missing ? Is there a way to force it using the format of without it?
@androiddeveloper Like I said, the answer depends on the OS. I think you should open a new question. If you are talking about Android specifically, perhaps Stack Overflow or Android Enthusiasts would be more fitting.
@slhck Well it’s the same OS, just with BusyBox installed. I asked if it’s possible (meaning : is there a command to use) to get the format that will be shown.
There are only THREE distinct times values stored for each of your files, as defined by the POSIX Standard : http://pubs.opengroup.org/onlinepubs/9699919799/ (see Base Definitions section -> 4. General Concepts -> 4.8 File Times Update)
Each file has three distinct associated timestamps: the time of last data access, the time of last data modification, and the time the file status last changed. These values are returned in the file characteristics structure struct stat, as described in .
atime is for Last data access timestamp. mtime is for Last data modification timestamp. ctime is for Last file status change timestamp.
Following examples show the difference among the atime, mtime and ctime, these examples are in GNU/Linux BASH. You can use stat -x in Mac OS X or other BSD Dist. to see the similar output format.
$ stat --version stat (GNU coreutils) 8.4 Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Michael Meskes. $ $ touch test $ stat test File: `test' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 811h/2065d Inode: 98828525 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 514/ rank) Gid: ( 514/ rank) Access: 2014-03-16 10:58:28.609223953 +0800 Modify: 2014-03-16 10:58:28.609223953 +0800 Change: 2014-03-16 10:58:28.609223953 +0800
When the file just be created, three timestamps are the same.
1. atime
First, let’s access the file’s data by reading it ( less or vim ), printing it out ( cat ) or copy it to another file ( cp ).
$ cat test #Nothing will be printed out, since the file is empty $ stat test File: `test' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 811h/2065d Inode: 98828525 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 514/ rank) Gid: ( 514/ rank) Access: 2014-03-16 10:59:13.182301069 +0800
2. ctime
Now let's change the file status, by changing the permission ( chmod ) or renaming it ( mv )
$ chmod u+x test $ stat stet File: `test' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 811h/2065d Inode: 98828525 Links: 1 Access: (0764/-rwxrw-r--) Uid: ( 514/ rank) Gid: ( 514/ rank) Access: 2014-03-16 10:59:13.182301069 +0800 Modify: 2014-03-16 10:58:28.609223953 +0800 Change: 2014-03-16 11:04:10.178285430 +0800
Note that until now, the contents (data) of the file is still the same as when it created.
3. mtime
Finally, let's modify the contents of the file by editing the file.
$ echo 'Modify the DATA of the file' > testing $ echo 'Modify the DATA of the file also change the file status' > testing $ stat testing File: `testing' Size: 56 Blocks: 8 IO Block: 4096 regular file Device: 811h/2065d Inode: 98828525 Links: 1 Access: (0764/-rwxrw-r--) Uid: ( 514/ rank) Gid: ( 514/ rank) Access: 2014-03-16 10:59:13.182301069 +0800 Modify: 2014-03-16 11:09:48.247345148 +0800
4. birth time
Also note that the newer version of stat (e.g. stat --version 8.13 in Ubuntu 12.04) has 4th timestamp information - the Birth Time (file creation time). Although it may not show the correct time for now:
$ stat --version stat (GNU coreutils) 8.13 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Michael Meskes. $ $ stat birth_time File: `birth_time' Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 805h/2053d Inode: 4073946 Links: 1 Access: (0664/-rw-rw-r--) Uid: ( 1000/ bingyao) Gid: ( 1000/ bingyao) Access: 2014-03-16 10:46:48.838718970 +0800 Modify: 2014-03-16 10:46:48.838718970 +0800 Change: 2014-03-16 10:46:48.838718970 +0800 Birth: -