如何在cronjob的长路径名称中正确使用模式列表?
问题描述
我每天需要将四个文件从一个文件夹移动到子文件夹。5月26日,待处理的是前一天的文件:
changes-ar-240525.txt changes-dp-240525.txt planned-ar-240525.txt planned-dp-240505.txt
原本我用四个cronjob逐个移动文件:
16 2 * * * mv /path/changes-ar-`date -d "1 day ago" "+\%y\%m\%d"`.txt /path/subfolder 17 2 * * * mv /path/changes-dp-`date -d "1 day ago" "+\%y\%m\%d"`.txt /path/subfolder 18 2 * * * mv /path/planned-ar-`date -d "1 day ago" "+\%y\%m\%d"`.txt /path/subfolder 19 2 * * * mv /path/planned-dp-`date -d "1 day ago" "+\%y\%m\%d"`.txt /path/subfolder
我想通过单个cronjob用模式列表完成,尝试了以下命令:
18 2 * * * mv /path/@(changes|planned)-@(ar|dp)-`date -d "1 day ago" "+\%y\%m\%d"`.txt /path/subfolder
但返回错误:
/bin/sh: 1: Syntax error: "(" unexpected
请问如何正确使用模式列表实现单个cronjob完成移动?
解决方法
出现错误是因为cron默认使用/bin/sh,而@(...)这种扩展模式是bash的专属特性,sh不支持。可以用以下几种方式解决:
方法1:指定bash执行cron命令
在cronjob开头明确调用bash,同时调整命令写法避免转义问题:
18 2 * * * bash -c 'mv /path/@(changes|planned)-@(ar|dp)-$(date -d "1 day ago" "+%y%m%d").txt /path/subfolder'
这里用单引号包裹命令内容,同时把反引号命令替换改成更现代的$()写法,减少转义麻烦。
方法2:使用POSIX标准的大括号扩展
如果不想依赖bash特性,可用sh支持的{a,b}大括号扩展,写法更通用:
18 2 * * * mv /path/{changes,planned}-{ar,dp}-`date -d "1 day ago" "+\%y\%m\%d"`.txt /path/subfolder
这种扩展是POSIX标准规定的,所有符合标准的shell都能识别,不需要额外配置。
方法3:编写独立bash脚本执行
把移动逻辑写到单独的脚本里,cron直接调用脚本,后续维护更方便:
- 创建脚本文件
/path/move_files.sh:
#!/bin/bash YESTERDAY=$(date -d "1 day ago" "+%y%m%d") mv /path/@(changes|planned)-@(ar|dp)-${YESTERDAY}.txt /path/subfolder
- 给脚本添加执行权限:
chmod +x /path/move_files.sh
- 在cron中添加任务:
18 2 * * * /path/move_files.sh
内容的提问来源于stack exchange,提问作者user24031531
相关产品推荐
相关产品推荐

