Linux与Windows路径转换

对于新写的代码,最好不要用下面的方式,而是在配置文件中定义BASE_PATH,路径的连接都使用os.path.join,这样代码自然就是跨平台的,对于遗留代码,可以通过下面的to_os_path快速提供平台兼容性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import sys
import os
import re
from typing import List, Tuple

# 如果确信path是Windows路径则返回True,否则返回False
def must_be_windows_path(path):
if len(path) >= 2 and path[1] == ':':
return True
if len(path) >= 2 and path[0] == '\\' and path[1] == '\\':
return True
return False

# 如果确信path是Linux路径则返回True,否则返回False
def must_be_linux_path(path):
if len(path) >= 1 and path[0] == '/':
return True
return False


class PathNormalizer:
def __init__(self, path_map_lst: List[Tuple[str, str]]):
"""
Args:
- path_map_lst List[Tuple[str, str]]: 通过列表指定Linux和Windows系统的路径前缀的匹配对
"""
self.l2w = {}
self.w2l = {}

for e in path_map_lst:
if must_be_linux_path(e[0]) or must_be_windows_path(e[1]):
linux_path = e[0]
windows_path = e[1]
else:
linux_path = e[1]
windows_path = e[0]
if linux_path[-1] != '/':
linux_path += '/'
if windows_path[-1] != '\\':
windows_path += '\\'
self.l2w[linux_path] = windows_path
self.w2l[windows_path] = linux_path

def __call__(self, path: str):
"""
会自动转换传入的路径匹配到当前环境的操作系统。
可以传入绝对路径或相对路径
也可以传入已经符合当前操作系统规则的路径,此时则不会修改

Args:
- path str: 需要转换的路径

Returns:
- str: 匹配当前环境操作系统的路径
"""
if sys.platform.lower() == 'linux':
return self.to_linux_path(path)
else:
return self.to_windows_path(path)

def to_linux_path(self, path):
if must_be_linux_path(path):
return path

for (windows_prefix, linux_prefix) in self.w2l.items():
if path.startswith(windows_prefix):
return linux_prefix + path[len(windows_prefix):].replace('\\', '/')
return path.replace('\\', '/')

def to_windows_path(self, path):
if must_be_windows_path(path):
return path

for (linux_prefix, windows_prefix) in self.l2w.items():
if path.startswith(linux_prefix):
return windows_prefix + path[len(linux_prefix):].replace('/', '\\')
return path.replace('/', '\\')


norm_path = PathNormalizer([
(r"\\192.168.1.107\e", "/mnt/107e"),
(r"\\192.168.1.99\database", "/mnt/99database"),
(r"I:", "/mnt/112"),
])


def test():
print(norm_path(r"I:\snapshot\abc"))


if __name__ == '__main__':
test()