Grep找到目标文件后无法执行复制操作的语法问题排查
问题分析与解决
你的问题出在shell大括号展开的顺序和grep的参数语法不匹配上,导致grep错误地把展开后的日期字符串当成了要搜索的文件,而非搜索模式的一部分。
为什么原来的命令会报错?
当你执行grep -m1 2021{245..274} {}时,shell会先把2021{245..274}展开成一串独立的字符串:
2021245 2021246 2021247 ... 2021274
此时grep的实际参数变成了:
grep -m1 2021245 2021246 ... 2021274 files/test/sample1.txt.txt
grep的语法是grep [选项] 模式 文件,所以它会把第一个字符串2021245当作搜索模式,后面的2021246到2021274都被当成要搜索的文件——但这些文件根本不存在,于是就出现了你看到的No such file or directory错误。
两种可行的修正方案
方案1:用进程替换传递所有日期模式
通过printf生成所有目标日期的列表,再让grep从这个列表读取搜索模式,这样就能避免shell展开带来的参数混乱:
find files/test/ -type f -exec grep -q -m1 -f <(printf "2021%03d\n" {245..274}) {} \; -exec cp -t files/new_location {} +
<(printf ...)是进程替换,会把printf输出的内容(每个日期一行)当作临时文件传递给grep-f选项让grep从这个临时文件读取所有搜索模式-q是静默模式,只返回匹配状态(不输出匹配内容),这样find只会在文件包含目标日期时执行后续的cp命令-m1确保找到第一个匹配后就停止搜索,提升效率
方案2:用正则表达式匹配日期范围(更高效)
如果日期范围是连续的,用正则表达式一次性匹配所有目标日期,不需要生成多个模式:
find files/test/ -type f -exec grep -q -m1 '2021(24[5-9]|2[5-6][0-9]|27[0-4])' {} \; -exec cp -t files/new_location {} +
正则表达式的含义:
24[5-9]:匹配245-2492[5-6][0-9]:匹配250-26927[0-4]:匹配270-274
整个表达式会匹配2021后面跟着245到274之间的所有数字,一次完成所有日期的匹配。
验证效果
执行修正后的命令后,你不会再看到grep的错误提示,所有包含目标日期的文件都会被复制到files/new_location目录下。
内容的提问来源于stack exchange,提问作者JT-66
相关产品推荐
相关产品推荐

