我有一系列名称格式为“foo.date.bar”的文件,其中“日期”是一个六位数字字段,例如 310715。
例如
foo.310715.bar
foo.260815.bar
foo.110815.bar
foo.040815.bar
我想根据文件名中的日期而不是任何文件元数据将它们排序为日期顺序,以便我的脚本可以删除其中的一些。通常我会在 Python 或 PHP 中执行此操作,因为这很容易,但我正在尝试学习如何在 Bash 中执行操作。我第一次尝试使用命令
for f in $( find $dir -type f | sort -r -t. -k 2 ); do
echo $f
done
但后来我意识到按数字或字母顺序对第二列进行排序是没有用的,我必须将其按日期排序。似乎没有任何方法可以告诉sort
如何将六位数字字段视为日期,或者如何将其视为三个两位数字列。我想知道下一步是否是使用sed
或tr
或类似的东西将六位数字字段变成sort
可以解析的东西?
预先感谢您的任何帮助,
MB
感谢大家的精彩回答,我从中学到了很多东西。
答案1
这是对 bash 数组的滥用;它将时间戳分开并根据 YYMMDD 顺序创建数组条目,然后按顺序打印数组。
declare -a array
for file in foo.*.bar
do
[[ $file =~ foo.([[:digit:]]{2})([[:digit:]]{2})([[:digit:]]{2}).bar ]] && \
{
index="${BASH_REMATCH[3]}${BASH_REMATCH[2]}${BASH_REMATCH[1]}"
array[$index]="$file"
}
done
for index in "${array[@]}"
do
echo $index
done
# or
printf "%s\n" ${array[@]}
答案2
如果您有 GNU 或 FreeBSD sort
,则可以在第一次使用后使用-V
或选项来交换日期格式(然后再次将日期格式更改回来):--version-sort
sed
sed
ls -1 |
sed -E -e 's/^(.*\.)(..)(..)(..)(.*)$/\1\4\3\2\5/' |
sort -V |
sed -E -e 's/^(.*\.)(..)(..)(..)(.*)$/\1\4\3\2\5/'
理想情况下,您应该只重命名文件,以便它们具有有用的日期格式。例如使用 perl 重命名实用程序prename
:
$ prename -v 's/^(.*\.)(..)(..)(..)(.*)$/$1$4$3$2$5/' *
foo.040815.bar renamed as foo.150804.bar
foo.110815.bar renamed as foo.150811.bar
foo.260815.bar renamed as foo.150826.bar
foo.310715.bar renamed as foo.150731.bar
$ ls -1 | sort -V
foo.150731.bar
foo.150804.bar
foo.150811.bar
foo.150826.bar
(顺便说一句,与大多数prename
操作不同,这个操作恰好是可逆的。如果需要,您可以再次运行它以将它们重命名回原来的名称)
答案3
以下管道序列首先用于将格式为sed
的文件名更改为.重新格式化的输出通过管道传送到“|”所在的位置用作字段分隔符,首先按 YY ( ) 排序,然后按 MM ( ) 排序,最后按 DD ( ) 排序。然后,排序后的输出通过管道返回到文件名被转换回原始格式的地方。*.DDMMYY.*
*|DD|MM|YY|*
sort
-k4n
-k3n
-k2n
sed
*.DDMMYY.*
sed 's/\.\([[:digit:]]\{2\}\)\([[:digit:]]\{2\}\)\([[:digit:]]\{2\}\)\./|\1|\2|\3|/' | \
sort -t'|' -k4n -k3n -k2n | \
sed 's/|\([[:digit:]]\{2\}\)|\([[:digit:]]\{2\}\)|\([[:digit:]]\{2\}\)|/.\1\2\3./'
使用以下文件示例:
$ ls *bar -1
abc.291015.bar
abc.291115.bar
abc.291215.bar
abc.301215.bar
foo.040815.bar
foo.150115.bar
foo.150914.bar
foo.260815.bar
foo.301216.bar
foo.310715.bar
xyz.010113.bar
该序列将产生以下结果:
xyz.010113.bar
foo.150914.bar
foo.150115.bar
foo.310715.bar
foo.040815.bar
foo.260815.bar
abc.291015.bar
abc.291115.bar
abc.291215.bar
abc.301215.bar
foo.301216.bar