重命名包含非 ASCII 文件的文件以附加其自己的 ASCII 日期时间

重命名包含非 ASCII 文件的文件以附加其自己的 ASCII 日期时间

多语言环境和 Linux 上的文件存储当然允许文件名中包含所有这些国际(亚洲)字符。但这会导致与其他系统同步的问题,因为国际字符都被其他系统视为 ???或者其他什么,并且它们不再是这些系统的唯一文件名(罪魁祸首是我们尝试同步的 MS Onedrive/Sharepoint)——同一目录中的两个文件具有不同的名称(亚洲字符),但具有相同数量的不幸的是,字符被视为具有相同的文件名,并且我们收到复制错误。除了重命名文件之外似乎没有其他解决方法。

我想简单地将文件自己的 ASCII 日期时间附加到它们的文件名中,这应该可以解决问题。

这个命令非常适合查找对我来说“有问题”的所有文件,可以这么说——它找到了 /path/to/files/ 和所有子文件夹中的文件和文件夹名称中的所有非 ASCII 字符:

find /path/to/files/ | grep -P "[\x80-\xFF]"

我需要对这些文件执行的操作是将基本文件名附加到文件自己的 ASCII 日期时间(按原样保留文件扩展名)。

几乎任何日期时间都可以,无论是根据统计数据的出生、修改、更改日期。这些返回的信息将起作用,例如:

stat -c '%y' filename

date -r filename

我不知道如何自动将文件的这些日期时间附加到第一个 find 命令列出的文件的基本文件名中。

答案1

zsh

#! /bin/zsh -
zmodload zsh/stat
zmodload zsh/files # for its builtin mv to speed things up.
set +o multibyte -o extendedglob

# comment-out the line below once you're satisfied it does what you want.
mv() { printf 'Would rename %s to %s\n' ${(q+)2} ${(q+)3}; }

ts_format='-%FT%T.%3.%z'

# we build a $ts_pattern to be able to identify files that already have
# had a timestamp appended, by obtaining a sample timestamp for the /
# directory, and replacing all digits in it with [0-9]. That assumes you
# don't use wildcard characters nor day/month/timezone names, am/pm in your
# $ts_format.
stat -F $ts_format -A ts_sample +mtime /
ts_pattern=${ts_sample//[0-9]/[0-9]}

for file in **/(*[$'\x80'-$'\xff']*~*$~ts_pattern(.*|))(DNod); do
  stat -LF $ts_format -A ts +mtime -- $file || continue
  case $file:t in
    (?*.*) mv -- $file $file:r$ts.$file:e;; # insert ts before extension
    (*)    mv -- $file $file$ts;;
  esac
done

我听说某些 Microsoft 操作系统存在包含字符的文件名问题,:因此您可能必须调整时间戳格式(此处采用毫秒精度的国际标准格式2020-08-23T08:14:38.318+0100)。这是标准strftime()格式指令,除了特定%<precision>.的亚秒部分zsh(在 中没有等效项strftime())。

相关内容