我将使用find
来打印最后修改时间(从纪元开始的秒数)和名称(用空格分隔),使用sort
来按最后修改时间从最新到最旧进行排序,使用awk
来 Select 每对中最旧的,并使用while
循环来重命名:
find . -type f -name '[0-9][0-9][0-9][0-9]_*' -printf '%T@ %p\n' | sort -nr |
awk '{sub(/^[^ ]* /,""); p = substr($0,1,4); num[p]++; name[p] = $0}
END {for(p in num) if(num[p] == 2) print name[p]}' |
while IFS= read -r file; do mv "$file" "${file}_old"; done
find
Select 名称以4位数字和下划线(-name '[0-9][0-9][0-9][0-9]_*'
)开头的所有文件(-type f
),并打印它们的最后修改时间(从纪元开始的秒)、空格、文件路径和换行符(-printf '%T@ %p\n'
).
sort
按数字(-n
)和逆序(-r
)排序.因此,更新的文件将首先出现.
在awk
脚本中,我们删除前导时间戳和后面的空格(sub(/^[^ ]* /,"")
),将文件名的前4个字符前缀存储在变量p
中(p = substr($0,1,4)
),在数组num
中计算具有该前缀的文件数(num[p]++
),将最后遇到的具有该前缀的文件名存储在数组name
中(name[p] = $0
).在END
处,我们循环数组num
的所有键,并且如果计数为2,则打印数组name
中的对应条目,其是遇到的具有该前缀的最后(第二个)名称,即,两个中最老的一个.
IFS=
保留前导(但在本例中不能有前导空格,因为find
Select 具有4个前导数字的文件)和尾随空格.
注意:如果您的文件名不包含换行符(但可以包含制表符或空格),则此方法有效.如果是这样,事情就稍微复杂一些,我们必须使用NUL字符(ASCII代码0)作为记录分隔符,因为它是唯一在文件路径中找不到的字符.使用GNU awk
(其他一些awk
不支持NUL记录分隔符):
find . -type f -name '[0-9][0-9][0-9][0-9]_*' -printf '%T@ %p\0' | sort -znr |
awk -v RS='\0' '
{sub(/^[^ ]* /,""); p = substr($0,1,4); num[p]++; name[p] = $0}
END {for(p in num) if(num[p] == 2) printf("%s\0", name[p])}' |
while IFS= read -d '' -r file; do mv "$file" "${file}_old"; done
在sort
(-z
)、GNU awk
(-v RS='\0'
)和read
(-d ''
)中,我们指出记录是无分隔的.在find
和awk
中,我们在每个记录的末尾打印NUL而不是换行符.