1

I know I can use the find command with options like -mtime and -ctime, but those expect a number to be set in the command.

In my case I don't care what the time is, I just want to find any files where the -ctime and -mtime are equal to each other. (Im on a Mac so technically its -mtime and -Btime)

Im having a harder time than I expected finding how to do this.

Edit: I’m trying to do this in macOS and the file system is APFS

ReLink
  • 25
  • 5

2 Answers2

1

As you can see here, creation time is not really stored on Unix-like systems. Some filesystems may support this feature and you can check the output of stat file command, for me the last line of this output is Birth: -. So in case you do have creation times, you could get files never modified by this:

find . -type f -print0 | xargs -0 stat -c "%n %W %Y" |
                         awk '$NF==$(NF-1) {$(NF-1)=$NF=""; print}'

%W will print birth time (probably 0 if not supported) and %Y the last modification time. The last awk command above prints only filenames where these times are matching.


for macOS:

find . -type f -print0 | xargs -0 stat -f "%N %B %m" |
                         awk '$NF==$(NF-1) {$(NF-1)=$NF=""; print}'

see also macOS stat man page

thanasisp
  • 5,855
  • 3
  • 14
  • 31
  • Creation time is not well-defined. For example, for a hard link to an existing file, is the creation time the creation of the link or the original inode? If the former, where is the creation time stored (since not in the inode)? – mpez0 Oct 06 '20 at 20:00
  • from what I understand on macOS creation time is kept as the "birth time". Also apparently the Linux and macOS versions of `stat` are slightly different so i had to make some changes, but I do believe it is working! `find . -type f -print0 | xargs -0 stat -f "%N %B %m" | awk '$NF==$(NF-1) {NF=NF-2; print}'` – ReLink Oct 06 '20 at 21:13
  • I’m pretty new to all this, but this command does seem to be giving me what I need. What would I need to add to this to have it just give me one file at a time instead of listing all that meet the criteria at the same time? – ReLink Oct 07 '20 at 10:29
  • @thanasisp ctim is the time the metadata was last modified ("status change" in struct stat), nothing to do with "creation time". atim is last content access, mtim is last content change. No other timestamps are in struct stat. – mpez0 Oct 07 '20 at 13:12
  • @mpez0 I do not use any `ctime` in my answer, I use `stat -c %W time of file birth, seconds since Epoch; 0 if unknown`. I just wrote ctime in comment meaning that creation (birth) time, maybe that was confusing. – thanasisp Oct 07 '20 at 13:20
  • @thanasisp. Yes, using "ctime" as creation time is confusing, since in Unix filesystems "ctime" means status change time. Which filesystems call creation time "ctime?" – mpez0 Oct 07 '20 at 14:17
  • This works perfectly. Just one more question though, combined with `head -1` i was able to get it to only show the first result, which is perfect. but lastly, how do i get this to only show the file name? it currently shows the 2 times after the name which is throwing off the next command thats needs to read that filename. – ReLink Oct 07 '20 at 15:03
  • I don't understand what you mean, could you update with an output line? Each line should have one filename only. – thanasisp Oct 07 '20 at 15:08
  • It does have only one line, but the output looks like the following `361.jpg 1601849382 1601997889` I need to get rid of the extra info so it just looks like `361.jpg`. I assume all those extra numbers are the birth and modified times. – ReLink Oct 07 '20 at 15:13
  • I am already doing this with the `awk` command, I cut two last fields. Did you executed the whole command (for macOS) including the last pipe to awk? – thanasisp Oct 07 '20 at 15:15
  • I believe so, I have it in its own `.sh.` file for testing, and the file contains exactly `find ~/Wallaware/B -type f -print0 | xargs -0 stat -f "%N %B %m" | awk '$NF==$(NF-1) {NF=NF-2; print}' | head -1` – ReLink Oct 07 '20 at 15:21
  • If you **do** use the exact command, consider updating to the GNU awk like [here](https://stackoverflow.com/questions/24332942/why-awk-script-does-not-work-on-mac-os-but-works-on-linux) I have seen SO questions with broken macOS awk frequently. Or update last command to `awk '$NF==$(NF-1) {$NF=""; $(NF-1)=""; print}'` – thanasisp Oct 07 '20 at 15:23
  • That was it! thank you. I installed `gawk` via homebrew, changed the command in the file from `awk` to `gawk` and it worked just fine. On a side note, is there anywhere I can download the binaries for these commands? id rather just include the command executable in the directory with my script, than to keep downloading things via homebrew ill likely never need again outside of the script im working on. – ReLink Oct 07 '20 at 15:28
  • I have no idea about macOS package system, I use only linux. Maybe do some search on the Stack Exchange sites for your query. Cheers. – thanasisp Oct 07 '20 at 15:31
0

I think this is not possible with just find, but you may filter these files using external tools, e.g. shell:

find . -type f -printf '%T@ %C@ %f\n' | while read mtime ctime fname; do
    [ "$mtime" == "$ctime" ] && echo "$fname"
done
Valery Panov
  • 274
  • 2
  • 6
  • When i run this I get "find: -printf: unknown primary or operator" – ReLink Oct 06 '20 at 17:15
  • 1
    These format strings are probably specific to Linux / GNU `find`. If this is crucial, you can probably install GNU `findutils` using Homebrew or etc. (But agree that the answer should explain this.) – tripleee Oct 06 '20 at 17:37
  • @ReLink BSD/OSX's `find` has no `-printf` option. You need GNU `find` for this option. – Léa Gris Oct 06 '20 at 17:37
  • Maybe try with `find -exec stat` with a suitable format string. – tripleee Oct 06 '20 at 17:40
  • I installed `findutils` via homebrew and tweaked the script a little but its not returning an expected result. `gfind ~/WallAware/B -type f -printf '%T@ %C@ %f\n' -regex ".*\.(jpg|gif|png|jpeg)" | while read mtime Btime fname; do [ "$mtime" == "$Btime" ] && echo "$fname" done` Im getting back `.DS_Store Photos` as output, when there is clearly a file in this folder that meets the criteria of btime and mtime being equal. – ReLink Oct 06 '20 at 18:20
  • You may try to debug this behavior by removing "| while ... " part: find will print out mtime, btime and file name, you will be able to check manually what's going on provided there are not too many files matching find's criteria. – Valery Panov Oct 07 '20 at 18:00