You are right … ctime
is the file's last status(i.e. meta data) change time.
However, in recent kernels, the support of the system call statx() is added ... That, when a file is queried with e.g. stat file
, should return some extended file attributes including btime
which is the birth/creation time of that file (Check first with stat file
to see if birth time is reported) ... A quick check on Ubuntu 22.04 shows that stat
indeed uses statx()
to get the btime
... See for example:
$ strace -e statx -v -s 0 stat filename
statx(AT_FDCWD, "filename", AT_STATX_SYNC_AS_STAT|AT_SYMLINK_NOFOLLOW, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_blksize=4096, stx_attributes=0, stx_nlink=1, stx_uid=1000, stx_gid=1000, stx_mode=S_IFREG|0664, stx_ino=22022834, stx_size=0, stx_blocks=0, stx_attributes_mask=STATX_ATTR_COMPRESSED|STATX_ATTR_IMMUTABLE|STATX_ATTR_APPEND|STATX_ATTR_NODUMP|STATX_ATTR_ENCRYPTED|STATX_ATTR_AUTOMOUNT|STATX_ATTR_MOUNT_ROOT|STATX_ATTR_VERITY|STATX_ATTR_DAX, stx_atime={tv_sec=1679481498, tv_nsec=733858313} /* 2023-03-22T13:38:18.733858313+0300 */, stx_btime={tv_sec=1679481214, tv_nsec=228264332} /* 2023-03-22T13:33:34.228264332+0300 */, stx_ctime={tv_sec=1679481498, tv_nsec=733858313} /* 2023-03-22T13:38:18.733858313+0300 */, stx_mtime={tv_sec=1679481498, tv_nsec=733858313} /* 2023-03-22T13:38:18.733858313+0300 */, stx_rdev_major=0, stx_rdev_minor=0, stx_dev_major=8, stx_dev_minor=2}) = 0
File: filename
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 802h/2050d Inode: 22022834 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu)
Access: 2023-03-22 13:38:18.733858313 +0300
Modify: 2023-03-22 13:38:18.733858313 +0300
Change: 2023-03-22 13:38:18.733858313 +0300
Birth: 2023-03-22 13:33:34.228264332 +0300
+++ exited with 0 +++
Therefore, you should be able to copy the creation time of a file to replace its modification time with something like this:
touch -m -d "$(stat -c '%w' file)" file
Or to replace both access and modification times add the -a
option to touch
as well … or drop the -m
option from touch
as it should then default to both.
Or, you can do the same for all the files in the current working directory with something like this:
for f in *
do
[ -f "$f" ] && touch -m -d "$(stat -c '%w' "$f")" "$f"
done