参考:DeepSeek - 探索未至之境

前言:Linux 系统下,在 Python 脚本第一行添加类似于#!/bin/python 的 shebang 行,然后给该 Python 脚本添加可执行权限后使用./xx.py 的方式执行该脚本却报错 Command not found,但是 shebang 行路径和执行权限都没有问题且命令行直接使用python xx.py可以正常运行

原因

这里报错内容是 Command not found,因此是对应的 shebang 行命令无法找到,而 shebang 行路径没有问题的话,那么大概率是在结尾处存在看不见的字符。
使用cat -A xx.py打印具有控制功能的字符,如换行符等,发现行尾字符出现^M 即\r,导致 shebang 行路径变为#!/bin/python\r,因此无法找到该命令导致的报错

对于 Windows 系统来说,每行通过 CRLF(\r\n) 标识符换行;而对于 Unix 系统来说,每行通过 LF(\n) 标识符换行,因此上述问题大概率是因为直接将 Windows 系统上的 Python 脚本文件直接复制到 Unix 系统再执行导致的报错

解决

可以使用  dos2unix xx.py  或  sed -i 's/\r$//' xx.py  去掉\r 转换为 Unix 系统的\n 换行符(即将 Windows 系统的 CRLF 换行符修改为 Unix 系统的 LF 换行符)

dos2unixpy.py 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import sys

# 不指定output_file时默认输出到命令行终端
def dos2unixpy(input_file, output_file=None):
"""Read input_file, replace CRLF with LF, write to output_file or stdout."""
with open(input_file, "rb") as rf:
raw = rf.read()

# Replace CRLF with LF (binary mode to handle exact bytes)
data = raw.replace(b"\r\n", b"\n")

if output_file:
with open(output_file, "wb") as wf:
wf.write(data)
else:
sys.stdout.buffer.write(data)

if __name__ == "__main__":
dos2unixpy("a.py", "b.py")