UNIX中基于文件内容的文件重命名

UNIX中基于文件内容的文件重命名,unix,awk,file-rename,batch-rename,Unix,Awk,File Rename,Batch Rename,我在文件中有日期和文件名。 两者都有一些价值,如下所示 我的要求是,我应该像FILENAME\u QUARTERDATE那样重命名文件 我的文件(myfile.txt)如下所示: QUARTERDATE: 03/31/14 - 06/29/14 FILENAME : LEAD field1 field2 34567 20.0 5,678 20.0 5,678 20.0 5,678 20.0 5,678 20.0 5,

我在文件中有日期和文件名。 两者都有一些价值,如下所示

我的要求是,我应该像FILENAME\u QUARTERDATE那样重命名文件

我的文件(myfile.txt)如下所示:

        QUARTERDATE:    03/31/14 - 06/29/14
        FILENAME   :    LEAD
field1  field2
34567
20.0    5,678
20.0    5,678
20.0    5,678
20.0    5,678
20.0    5,678
我希望文件名为LEAD_201402.txt 文件中的日期范围是第二季度,所以我给出的是201402

提前感谢您的回复。

季度是如何定义的?
newname=$(awk '/QUARTERDATE/ { split($4, d, "/"); 
                               quarter=sprintf("%04d%02d", 2000+d[3], int((d[1]-1)/3)+1); }
               /FILENAME/ { fn = $3; print fn "_" quarter; exit; }' "$file")
mv "$file" "$newname"
正如在对主要问题的评论中所指出的那样,这一问题尚未明确界定


上一季度的季度日期行中会显示哪些数据?第一季度会以前一年的12月开始吗?第二季度的结束日期可能是7月(或4月的第一季度,或10月的第三季度,或1月的第四季度)?由于第二季度的第一个日期是3月,因此需要了解这些替代方案。一个季度是否可以同时早开始晚结束(14周的一个季度)

答复如下:


第二季度的季度日期将从4月的第一个星期一开始,到6月的最后一个星期日结束

触发了一个反响应:


2014年03月31日是星期一,但几乎不是四月的星期一。这主要意味着你对季度的定义还不清楚。例如,明年,2015-03-30是星期一,但“四月的第一个星期一”是2015-04-06。2015年3月的最后一个星期日是2015年3月29日。那么2015年3月30日星期一到2015年4月05日星期日属于哪个季度,为什么?如果您不知道(如何和为什么),我们无法可靠地帮助您

似是而非的工作假说
  • Y2K的教训已经被遗忘了(该死,为什么今年还要用两位数呢!)
  • 四分之一的时间为整周
  • 季度从周一开始,周日结束
  • 季度与日历季度保持一致,而不是在一年中四处漂流。(91天中有13周,一年中有4个这样的季度,但在普通年份中有一个额外的一天,在闰年中有两个额外的一天,这意味着偶尔你会有14周的季度,以确保事情保持一致。)
  • 季度中第一个日期的日期将接近1月1日、4月1日、7月1日或10月1日,但月份可能是12月、3月(如问题所述)、6月或9月
  • 季度中最后一个日期的日期将接近3月31日、6月30日、9月30日、12月31日,但月份可能是4月、7月、10月或1月
  • 通过将1模12(范围为1..12的值,而不是0..11)添加到起始月,您应该在日历季度中以一个月结束
  • 通过减去1模12(值再次在1..12范围内)到月底,您应该在日历季度结束一个月
  • 如果数据有效,“开始+1”和“结束-1”月份应在同一季度
  • 如果开始日期是12月(但这表明是下一年的第一季度),那么年初可能会减少1
  • 如果结束日期为1月,则结束年份可能会缩短一个月(但这表示上一年的第四季度)
更具弹性的代码 尽管有上述描述,但仍然可以编写代码来检测季度,而不管季度开始和结束日期的任何或所有特性。这段代码借鉴了一点,但该算法对日历和季度开始和结束日期的反复无常更具弹性

#!/bin/sh

awk '/QUARTERDATE/ {
         split($2, b, "/")
         split($4, e, "/")
         if      (b[1] == 12) { q = 1; y = e[3] }
         else if (e[1] ==  1) { q = 4; y = b[3] }
         else
         {
             if (b[3] != e[3]) {
                 print "Year mismatch (" $2 " vs " $4 ") in file " FILENAME
                 exit 1
             }
             m = int((b[1] + e[1]) / 2)
             q = int((m - 1) / 3) + 1
             y = e[3]
         }
         quarter = sprintf("%.4d%.2d", y + 2000, q)
     }
     /FILENAME/ {
         print $3 "_" quarter
         # exit
     }' "$@"
m
的计算将开始月份加1与结束月份减1相加,然后将整数除以2。对于已经处理过的极端情况,这总是会产生一个正确季度的月数

与文件名关联的
退出
前面的注释允许更轻松地进行测试。当分别处理每个文件时,如Barmar的示例中所示,
exit
是一个重要的优化。请注意,如果输入来自标准输入,则错误消息会给出一个空文件名。(顺便说一句,我不知道如何将错误消息打印到标准错误而不是标准输出,而不是通过平台特定的技术,例如
打印“message”>“/dev/stderr”
打印“message”>“/dev/fd/2”

给出该样本输入数据(从2014年第一季度到2015年第二季度的6个季度的半合理开始和结束日期):

此脚本的输出为:

LEAD_201401
LEAD_201402
LEAD_201403
LEAD_201404
LEAD_201501
LEAD_201502

您可以在合理的范围内调整季度的开始和结束日期,您仍然可以获得所需的输出。但要时刻警惕历法计算;它们几乎总是比你预期的更难。

上一季度的季度日期行中会出现什么数据?第一季度会以前一年的12月开始吗?第二季度的结束日期可能是7月(或4月的第一季度,或10月的第三季度,或1月的第四季度)?由于第二季度的第一个日期是3月,因此需要了解这些替代方案。一个季度能否同时早开始晚结束(14周的季度)?第二季度的季度日期将从4月的第一个星期一开始,到6月的最后一个星期日结束。2014-03-31是星期一,但几乎不是4月的星期一。这主要意味着你对季度的定义还不清楚。例如,明年,2015-03-30是星期一,但“四月的第一个星期一”是2015-04-06。2015年3月的最后一个星期日是2015年3月29日。那么2015年3月30日星期一到2015年4月05日星期日属于哪个季度,为什么?如果你不知道,我们无法可靠地帮助你。我会让事情变得简单。。。。将假定2014年第2季度。。。。季度开始日期肯定不会超过本月1日(即4月1日)。1日应为星期一,或从4月1日开始的第一个星期一,如3月31日、30日、29日……等等,均应为星期一。本季度的同一截止日期也不得超过6月31日。。。31日应为星期日或31日之前的某一天,即6月31日星期日;必须换一个新的c
LEAD_201401
LEAD_201402
LEAD_201403
LEAD_201404
LEAD_201501
LEAD_201502