这是一个自我回答的问题,其他人也可能会觉得有用。
在 Dolphin 中,我有时会在按名称排序和按修改日期排序之间切换。然而,这可能很烦人,因为 Dolphin 不会仅更改我所在文件夹的顺序。它会更改所有内容。所以我想知道如何修复修改日期以匹配名称顺序,以便在 Dolphin 中的名称和日期之间切换时特定目录不受影响。
答案1
事实证明这非常简单。
for FILE in *; do touch -- "$FILE"; sleep 0.001; done # sort
如果你想递归地进行:
for FILE in **/*; do touch -- "$FILE"; sleep 0.001; done # sort
这# sort
只是一条评论。目的是为了方便向后搜索命令。
答案2
你的方法(特别是添加sleep 0.001
通话之前的通话)仅适用于时间戳具有亚秒精度的系统和文件系统,即使如此,在某些系统和文件系统上,例如具有 ext4 文件系统的 Linux,即使时间戳具有纳秒分辨率,您也会发现某些批次的文件将具有相同的精度时间戳(参见linux:触摸日期精度和为什么 Linux 中的文件系统时间总是比系统时间晚一些毫秒?了解详情)。
在此之后:
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
(甚至 a 也sleep 0.001
可能无济于事,touch
在我的系统上运行已经花费了超过 1 毫秒,正如您从上面的时间戳中可以看出的那样)。
更好touch -d '0.000000001 second ago'
(假设 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
其中touch
请求一个显式时间戳,它使用向系统发出的全精度时钟时间请求来计算,而不是让系统选择当前缓存的 fs 时间,因此您几乎可以保证两个后续调用将获得不同的时间戳,但这会在时间戳不支持亚秒精度的地方仍然不起作用。
如果使用 zsh (并且与 GNUtouch
或兼容),您可以这样做:
zmodload zsh/datetime
now=$EPOCHSECONDS
for file ( *(NOn) ) touch -d @$((now--)) -- $file
或者使用标准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
}
哪里$EPOCHSECONDS
是当前的 Unix 纪元时间,*(NOn)
类似于*
但N
启用了 ULLGLOB 并且文件O
按n
ame 反向排序(大写 O 反向),因此您得到与 中相同的顺序ls -r
。然后我们将时间戳设置为相隔一秒,回溯到过去。
答案3
正如其他人已经说过的那样ls
,并且(echo) *
排序不同。
如果你想像ls
( 或者ls -[some option]
, ie排序) 排序ls -r
,你可以简单地使用它而不是*
.
另请注意,“*”本质上是不安全的,因为它扩展为所有文件名的列表,这些文件名可以(在大型目录中)使生成的命令行超过行长度限制。 shell(取决于 shell、版本……)将响应“命令行太长”之类的错误。
最后,顺便说一句:不将 shell 变量命名为大写是一个安全的习惯。系统变量(即“PATH”、“SHELL”、“OPTARG”等)通常都是大写,如果您以相同的方式命名自己的变量,则可能会面临(取消)设置此类变量的风险。在您自己的脚本中使用混合(或小写)大小写,这样您就安全了。
ls |\
while read fFile ; do
touch fFile
done