Your approach (especially the one before you added the sleep 0.001
call) only works on systems and file systems where time stamps have subsecond precision, and even then, on some, like on Linux with ext4 file systems, even though timestamps have nanosecond resolution, you'll find that some batches of files will have the same timestamp (see linux: touch date precision and Why is filesystem time always some msecs behind system time in Linux? for details).
Here after a:
for f ({1..20}) touch $f
$ ls --full-time -lrt
total 0
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.183520078 +0100 2
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.183520078 +0100 1
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.187520223 +0100 3
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.191520368 +0100 6
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.191520368 +0100 5
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.191520368 +0100 4
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.195520512 +0100 8
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.195520512 +0100 7
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.199520657 +0100 9
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.199520657 +0100 10
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.203520802 +0100 13
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.203520802 +0100 12
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.203520802 +0100 11
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.207520947 +0100 15
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.207520947 +0100 14
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.211521092 +0100 17
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.211521092 +0100 16
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.215521237 +0100 19
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.215521237 +0100 18
-rw-r--r-- 1 chazelas chazelas 0 2023-06-26 07:41:04.219521381 +0100 20
(and even a sleep 0.001
may not help, touch
already takes over 1ms to run on my system as you can tell from those timestamps above).
It's better with touch -d '0.000000001 second ago'
(assuming GNU touch
):
$ strace -qqe /utime touch -d now a
utimensat(0, NULL, NULL, 0) = 0
$ strace -qqe /utime touch -d '0.000000001 second ago' a
utimensat(0, NULL, [{tv_sec=1687765504, tv_nsec=213757695} /* 2023-06-26T08:45:04.213757695+0100 */, {tv_sec=1687765504, tv_nsec=213757695} /* 2023-06-26T08:45:04.213757695+0100 */], 0) = 0
Where touch
requests an explicit timestamp which it computes using a full precision clock time request to the system as opposed to letting the system pick the current cached fs time, so you're almost guaranteed that two subsequent calls will get a different timestamp, but that would still not work wherever timestamps don't support subsecond precision.
If using zsh (and with GNU touch
or compatible), you could do:
zmodload zsh/datetime
now=$EPOCHSECONDS
for file ( *(NOn) ) touch -d @$((now--)) -- $file
Or with standard touch
:
zmodload zsh/datetime
now=$EPOCHSECONDS
for file ( *(NOn) ) {
TZ=UTC0 strftime -s t %Y%m%d%H%M.%S $((now--)) &&
TZ=UTC0 touch -t $t -- $file
}
Where $EPOCHSECONDS
is the current Unix epoch time and *(NOn)
is like *
but with N
ULLGLOB on and with the files O
rdered by n
ame in reverse (captial O to reverse) so you get the same order as in ls -r
. Then we make the timestamps one second apart going back in time.
*
is not equivalent tols
.*
has the following semantics: https://unix.stackexchange.com/a/368325/43400, it sorts based sorting order in the current locale – Ferrybig Jun 25 '23 at 14:05ls
, and would work in a system with nols
at all! And at least in zsh you can also set the ordering using the extended glob syntax :) – Marcus Müller Jun 25 '23 at 17:05ls
. – Stéphane Chazelas Jun 26 '23 at 07:25extendedglob
(unless you also turn offbareglobqual
after which glob qualifiers can still be expressed with the(#q...)
extendedglob operator). – Stéphane Chazelas Jun 26 '23 at 07:28