我的文件夹之一包含以下格式的文件:
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
您可以使用awk
and 其字符串比较运算符。
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; }'