Bash拼接换行字符串发邮件时最后一行未换行问题
问题根因
你写的message拼接逻辑本身没有问题,本地echo "$message"输出正常就是最好的证明。格式错乱完全是内容传给mail工具的环节出的问题,核心原因有两个:
- 换行符不符合邮件传输标准
按照邮件协议RFC 5322要求,邮件正文的行分隔符必须是CRLF格式(也就是\r\n,回车+换行组合),你脚本里拼接的是Unix系统原生的纯LF换行符(\n)。终端对纯LF换行兼容性很好,能正常识别为换行,但不少版本的mail发送组件、邮件客户端不认孤立的LF,会把它当成普通空白字符,直接导致相邻行被合并到同一行显示。 - 变量传参没加双引号触发了shell的单词拆分
如果你调用mail的时候没给$message加双引号——比如写了echo $message | mail xxx@xx.com,或者直接把$message当参数传给mail——shell会自动把变量里所有的换行、制表符、连续空格都当成分隔符,拆分后再传给命令,这些分隔符最终会被替换成单个空格。受mail自身输入解析逻辑的影响,不一定所有换行都会被替换成空格,经常就表现为最后几行被合并到一起。
顺便提一句你脚本里的逻辑bug:检测到无文件夹时你直接echo "No folders found",但这段内容没有赋值给message,真到无文件夹的场景,你发出去的邮件里根本看不到这段提示。
修复方法
- 先把空场景的提示内容赋值给
message,不要直接echo打印 - 所有引用
message变量的地方一律加双引号,避免shell自动拆分内容 - 拼接内容时直接用CRLF当换行符,避免mail组件识别错误
- 不要用命令替换的方式传递正文(命令替换会自动删掉内容末尾所有连续换行,很容易触发格式问题),直接用双引号包裹变量通过管道传给mail即可
修正后的参考脚本:
#!/bin/bash message="" CRLF=$'\r\n' for f in /mnt/backup/*; do if [ -d "$f" ]; then message+="${f} is a folder${CRLF}" fi done if [ -z "$message" ]; then message="No folders found${CRLF}" fi # 发邮件示例,主题和收件人按实际情况替换 echo "$message" | mail -s "Backup directory scan result" admin@example.com
如果改完还是有格式问题,可以在管道里加个换行转换工具处理下:echo "$message" | unix2dos | mail -s "xxx" admin@example.com
内容的提问来源于stack exchange,提问作者Der Korrigierer
相关产品推荐
相关产品推荐

