获取名称中包含小于或等于给定输入日期的日期值的文件

获取名称中包含小于或等于给定输入日期的日期值的文件

我的文件夹之一包含以下格式的文件:

3_20150412104422154033.txt
3_2015041211022775012.txt
3_20150412160410171639.txt
3_20150412160815638933.txt
3_20150413161046573097.txt
3_20150413161818852312.txt
3_20150413163054600311.txt
3_20150413163514489159.txt
3_2015041321292659391.txt
3_20150414124528747462.txt
3_20150414125110440425.txt
3_20150414134437706174.txt
3_20150415085045179056.txt
3_20150415100637970281.txt
3_20150415101749513872.txt

我想检索那些日期值小于或等于我的输入日期值的文件。

例如,如果我给出“3_20150414”(3_YYYYMMDD),我希望输出是文件名

3_20150412104422154033.txt
3_2015041211022775012.txt
3_20150412160410171639.txt
3_20150412160815638933.txt
3_20150413161046573097.txt
3_20150413161818852312.txt
3_20150413163054600311.txt
3_20150413163514489159.txt
3_2015041321292659391.txt
3_20150414124528747462.txt
3_20150414125110440425.txt
3_20150414134437706174.txt

我可以通过发出如下命令来列出文件:

ls -l | grep '20150413\|20150414' |awk '{print $NF}'

但我正在努力寻找一个<=匹配。

答案1

您可以使用awkand 其字符串比较运算符。

ls | awk '$0 < "3_20150415"'

在变量中:

max=3_20150414 export max
ls | LC_ALL=C awk '$0 <= ENVIRON["max"] "z"'

此处与“z”连接可确保比较是字符串比较,并允许当天的任何时间,因为在语言C环境中,数字在 之前排序z

在 中zsh,您还可以执行以下操作:

print -rC1 -- *.txt(e['[[ $REPLY < ${max}z ]]'])

答案2

grep没有 ≤ 运算符本身,但是有一种笨拙的方法可以伪造它。您需要 0 年(或 1 年;以第一年为准)到 20150414 之间的所有日期。(我假设 BC 日期不在表中。)将此范围分解为可以通过正则表达式匹配的子范围:

  • 0 到 1999 年 — 所有年份都以 0 或 1 开头,因此 grep for [01].
    (假定所有正则表达式都锚定在行的开头,紧接“3_”之后。)
  • 2000 年到 2009 年 — 正则表达式200.
  • 2010 年到 2014 年 — 正则表达式201[0-4].
  • 2015 年第 1 个月到第 3 个月 — 20150[1-3].
  • 2015 年第 4 个月第 1 日至第 9 日 —2014040
  • 2015 年第 4 个月第 10 至 14 天 —2014041[0-4]

然后把它们放在一起:

grep -E '3_([01]|200|201[0-4]|20150[1-3]|2015040|2015041[0-4])'

ls -l当然,它为您提供了许多您不需要的有关文件的信息(模式、所有者、修改时间等),因此您可以awk '{print $NF}'将其删除并仅保留文件名。这是低效且容易出错的(如果文件名中包含空格或制表符,则会中断)。解析来自的输出从来ls都不是一个好主意,但是您可以通过使其更简单一点来使其更安全:只是不要获取您不想要或不需要的信息,然后您就不需要丢弃它。

ls | grep -E '3_([01]|200|201[0-4]|20150[1-3]|2015040|2015041[0-4])'

应该足够好了。

但是构建由六部分组成的正则表达式非常乏味且容易出错,并且很难(尽管并非不可能)编写脚本。这是一个更干净的方法:

ls | awk 'substr($1, 3, 8) <= 20150414'

这会提取从第三个位置(即“3_”之后)开始的八个字符,并将其与 20150414 作为两个八位数字进行比较。

答案3

使用您的示例的可能解决方案:

ls -l | grep '3_2015' | awk -v d='3_20150414' '{ s = substr($NF, 1, 10); if (length(s) == 10 && s <= d) print $NF; }'

我稍微改变了你的 grep 模式,并将搜索值作为参数传递给awk我们只是比较字符串以输出所需内容的地方。
还有很多文章为什么你不应该解析ls所以我用 find 稍微改变一下:

find . -type f -name '*3_2015*' -printf "%f\n" | awk -v d='3_20150414' '{ s = substr($NF, 1, 10); if (length(s) == 10 && s <= d) print $NF; }'

相关内容