通过Bash脚本按文件大小发送邮件的需求咨询及问题排查
问题解决:Shell脚本按文件大小发送邮件的优化
问题描述
我在指定路径下有一些文件,其中包含大于10M的文件。需要编写Shell脚本实现:仅当文件大小小于5M时,将其作为附件发送邮件;当文件大小在5M到10M之间时,仅在邮件中高亮显示文件路径。我尝试了如下脚本,但出现「Message file too long」警告,恳请指导解决。
原脚本:
#!/bin/bash cd /opt/alb_test/alb/albt1/Source/alb/al/conversion/scripts #Sending Email ls *.xlsx -1 > test.txt while read line do mailx -s "Test Email" -a ${line} -s "Attaching files less than 5 MB" abc@testmail.com,def@gmail.com << EOM Hi, Sending the Files EOM done<test.txt
问题分析
- 重复设置主题参数:原脚本两次使用
-s参数,导致mailx参数解析混乱,且每个文件单独发送一封邮件,效率低下。 - 未做文件大小判断:不管文件多大都尝试作为附件发送,当文件超过邮件系统的附件大小限制时,就会触发「Message file too long」警告。
- 文件遍历方式不可靠:用
ls生成列表再read的方式,遇到文件名含空格时会拆分错误,导致处理失败。
解决方案脚本
#!/bin/bash # 目标文件路径 TARGET_DIR="/opt/alb_test/alb/albt1/Source/alb/al/conversion/scripts" # 切换目录失败则直接退出 cd "$TARGET_DIR" || exit 1 # 初始化邮件内容和附件列表 mail_body="Hi,\n\n" attach_list="" # 遍历目录下的xlsx文件 for file in *.xlsx; do # 跳过非文件(无匹配xlsx时,*.xlsx会作为字符串存在) [[ -f "$file" ]] || continue # 获取文件大小(MB单位,向上取整) file_size=$(du -m "$file" | awk '{print $1}') if (( file_size < 5 )); then # 小于5M,加入附件列表 attach_list+=" -a \"$file\"" elif (( file_size >= 5 && file_size <= 10 )); then # 5-10M,高亮绝对路径加入邮件内容 mail_body+="*$(realpath "$file")*\n" fi # 大于10M的文件直接忽略 done # 补充邮件结尾 mail_body+="\nRegards,\nAutomated Script" # 发送邮件:分有附件/无附件两种情况 if [[ -n "$attach_list" ]]; then # 用eval处理带空格的文件名参数 eval "mailx -s \"Files Status: Attachments Included\" $attach_list abc@testmail.com,def@gmail.com << EOM $(echo -e "$mail_body") EOM" else mailx -s "Files Status: No Attachments" abc@testmail.com,def@gmail.com << EOM $(echo -e "$mail_body") EOM fi
关键改进点
- 可靠的文件遍历:用
for file in *.xlsx直接遍历,配合[[ -f "$file" ]]处理无匹配文件的场景,避免文件名空格导致的拆分错误。 - 大小判断逻辑:用
du -m获取MB单位的文件大小,通过整数比较实现精准的区间判断。 - 统一发送邮件:收集所有符合条件的附件和内容后,一次性发送邮件,避免多次发送的冗余。
- 空格兼容:用双引号包裹文件名,
eval解析附件列表,确保含空格的文件能正确作为附件。 - 清晰的邮件内容:用
*包裹路径实现高亮,realpath提供绝对路径,让收件人明确文件位置。
内容的提问来源于stack exchange,提问作者Jenifer
相关产品推荐
相关产品推荐

