如何使用Python将Windows格式TXT文件转换为Unix格式
完全可以通过Python实现文本文件Windows→Unix行尾格式的自动校验、转换,且能把这套逻辑嵌入subprocess执行流程,从根源上避免行尾错误,解决执行后返回码无法识别格式异常的问题。
问题本质
Windows系统文本行尾为\r\n(CRLF格式),Linux/Unix系统文本行尾为\n(LF格式)。你碰到的filename.sh: line 4: $'\r': command not found报错,是因为shell把每行末尾残留的\r字符识别成了独立命令,解析失败抛出的错误。
你提到用plink运行同个文件能正常执行,是因为plink默认传输规则会自动对文本文件做CRLF→LF的隐式转换,不是文件本身格式符合Unix要求。
至于执行报错后$?拿到返回码为0的问题,是因为shell只会把脚本最后一条执行成功的命令的返回值作为整个脚本的退出码,前面行尾解析错误不会修改最终返回码,所以绝对不能靠脚本执行后的返回码判断行尾格式问题,必须把校验转换逻辑放在脚本执行前做前置处理。
实现方式
不需要手动修改编辑器EOL配置,也不需要强依赖系统的dos2unix工具,两种实现路径可选:
- 原生Python实现:跨平台兼容性最好,不依赖外部命令
- subprocess调用系统命令实现:符合命令行调用的需求
可直接复用的完整实现(含subprocess流程集成)
下面的代码会在调用脚本执行前,自动检测文件行尾格式,发现CRLF就自动转成LF,再执行脚本,从根源避免行尾报错:
import os import subprocess def fix_crlf_to_lf(file_path: str) -> bool: """ 检测目标文件是否包含Windows CRLF行尾,存在则自动转换为Unix LF格式 返回True表示执行了格式转换,返回False表示文件原本就是LF格式无需修改 """ # 二进制模式读写,规避不同文件编码导致的读取失败 with open(file_path, 'rb') as f: raw_content = f.read() if b'\r' not in raw_content: return False # 替换所有CRLF、孤立CR为LF fixed_content = raw_content.replace(b'\r\n', b'\n').replace(b'\r', b'\n') with open(file_path, 'wb') as f: f.write(fixed_content) return True def run_linux_script(script_path: str, *script_args): # 执行前先做行尾校验修复 if fix_crlf_to_lf(script_path): print(f"[提示] {script_path} 存在Windows行尾格式,已自动转换为Unix格式") # 补执行权限 os.chmod(script_path, 0o755) # 调用subprocess执行脚本 process = subprocess.run( [os.path.abspath(script_path), *script_args], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) return process # 调用示例 if __name__ == "__main__": exec_result = run_linux_script("./your_script.sh") print("=== 脚本执行输出 ===") print(exec_result.stdout) print("=== 脚本错误输出 ===") print(exec_result.stderr) print(f"=== 脚本退出码:{exec_result.returncode} ===")
如果你要通过subprocess调用系统命令完成转换,可以把上面代码里的fix_crlf_to_lf函数替换成下面的实现,本质是调用Linux自带的sed命令删除行尾的\r字符:
def fix_crlf_to_lf(file_path: str) -> bool: # 先检测是否存在CRLF with open(file_path, 'rb') as f: if b'\r' not in f.read(): return False # 调用sed命令原地替换 subprocess.run( ["sed", "-i", "s/\r$//", file_path], check=True, capture_output=True ) return True
注意这个方案依赖运行环境存在sed命令,跨平台兼容性弱于原生Python读写的方案。
内容的提问来源于stack exchange,提问作者rnd om

