一、问题背景
在CentOS系统中执行Shell脚本时,若发现使用 cp -f 命令后目标文件名末尾多出一个问号(如 file.txt? ),通常是由于跨平台编辑脚本导致的换行符冲突。此问题可能引发文件路径解析错误、脚本执行中断,甚至影响自动化流程的稳定性。
二、核心原因:CRLF与LF的换行符差异
Windows与Linux的换行符区别
Windows:使用 CRLF(\r\n)作为换行符,其中 CR(\r)为回车符。
Linux:仅使用 LF(\n)作为换行符。
问题触发场景
若脚本在Windows环境下编辑后直接上传至Linux系统,变量中的 \r 字符会被保留。
当变量用于文件路径时(如 target_file=$1\r),\r 会被Linux解析为普通字符,显示为问号(?)。
三、解决方案:使用dos2unix修复脚本格式
1. 安装dos2unix工具
在CentOS 7中,通过以下命令安装:
sudo yum install dos2unix -y # 默认仓库安装
2. 转换脚本换行符
执行以下命令清除Windows换行符:
dos2unix your_script.sh # 转换单个文件 dos2unix *.sh # 批量转换所有脚本
关键参数说明:
-n:保留原文件时间戳。
-k:强制保留UTF-8 BOM头(适用于特殊编码文件)。
3. 验证转换结果
通过 cat -v 检查隐藏字符:
cat -v your_script.sh | grep '^M' # 若输出为空,说明CR已清除
四、其他辅助解决措施
规范脚本变量引用
在操作文件路径时,始终用双引号包裹变量,避免空格或特殊字符解析异常:
cp -f "$source" "${target}/" # 末尾添加`/`确保目标为目录
清理变量中的控制字符
若变量值通过外部输入获取,可使用 tr 命令过滤 \r:
clean_target=$(echo "$target" | tr -d '\r')
编辑器配置预防
在Windows端使用代码编辑器(如VS Code、Notepad++)时,手动设置换行符为 LF。
通过Git全局配置避免换行符转换冲突:
git config --global core.autocrlf input
五、操作验证与效果
执行修复后的脚本
sh -x your_script.sh # 启用调试模式,观察变量实际值
检查目标文件