2009-12-04 44 views
5

Có cách nào đơn giản để có được đường dẫn nhạy cảm "thật" từ một đường dẫn trường hợp thấp hơn không. Giống như ngược lại của os.path.normcase.Đảo ngược os.path.normcase trên Windows

Ví dụ, hãy xem xét các thư mục:

c:\StackOverFlow 

Nếu tôi đã đoạn sau, làm thế nào để có được d_real?

>>> import os 
>>> d = os.path.normcase('C:\\StackOverFlow') # convert to lower case 
>>> d 
'c:\\stackoverflow' 
>>> d_real = ... # should give 'C:\StackOverFlow' with the correct case 
+0

'os.path.join ('c:', 'stackoverflow')' cung cấp cho bạn 'c: stackoverflow', * not *' c: \ stackoverflow', như được giải thích trong tài liệu (= đường dẫn tương đối) vào thư mục hiện tại trên ổ đĩa được chỉ định). –

+0

Đúng, tôi không kiểm tra mã ví dụ của mình. Sẽ sửa nó. Cảm ơn. – pkit

Trả lời

0

Hack cách tiếp cận Dirty,

import glob 
... 
if os.path.exists(d): 
    d_real = glob.glob(d + '*')[0][:len(d)] 
+0

glob.glob (d + '*') trả về một danh sách trống trên Windows (ít nhất là đối với tôi) – jhwist

+0

@jhwist, tôi đã thử nghiệm nó trên Windows và nó hoạt động. Bạn đã sử dụng cái gì cho 'd'? –

+0

Hmmm, có thể là một số kết hợp các đường dẫn kiểu Cygwin, 'd =" c:/existing_file "' – jhwist

1

Tôi sẽ không xem xét giải pháp này đơn giản, nhưng những gì bạn có thể để là:

import os 
d = os.path.normcase('C:\\StackOverFlow') 
files = os.listdir(os.path.dirname(d)) 
for f in files: 
    if not d.endswith(f.lower()): 
    continue 
    else 
    real_d = os.path.join(os.path.dirname(d), f) 

Nó có lẽ không hiệu quả (tùy thuộc vào số lượng tệp trong thư mục). Nó cần tinh chỉnh cho các thành phần đường dẫn (giải pháp của tôi thực sự chỉ sửa trường hợp của tên tệp và không quan tâm đến tên thư mục). Ngoài ra, có thể os.walk có thể hữu ích khi đi ngang qua cây.

-1

Chắc chắn xấu xí, nhưng niềm vui:

def getRealDirPath(path): 
    try: 
     open(path) 
    except IOError, e: 
     return str(e).split("'")[-2] 

Dĩ nhiên:

  • công trình chỉ với dirs
  • sẽ buggy nếu dir không thể được mở cho một lý do khác

Nhưng vẫn có thể hữu ích nếu bạn không cần nó cho loại mã "sống hay chết".

Cố gắng grep lib chuẩn để tìm cách họ tìm thấy đường dẫn thực nhưng không thể tìm thấy nó. Phải ở C.

Đó là bẩn hack trong ngày, thời gian tới chúng tôi sẽ sử dụng một regexp trên stacktrace chỉ vì chúng ta có thể :-)

+0

Không hoạt động ... – schlamar

0

Bạn có thể làm điều này bằng cách kết nối GetShortPathNameGetLongPathName. Điều này có thể trong lý thuyết không hoạt động vì bạn có thể vô hiệu hóa tên tập tin ngắn trên Windows với một số thiết lập cấu hình. Dưới đây là một số mẫu mã sử dụng ctypes:

def normcase(path): 
    import ctypes 
    GetShortPathName = ctypes.windll.kernel32.GetShortPathNameA 
    GetLongPathName = ctypes.windll.kernel32.GetLongPathNameA 
    # First convert path to a short path 
    short_length = GetShortPathName(path, None, 0) 
    if short_length == 0: 
     return path 
    short_buf = ctypes.create_string_buffer(short_length) 
    GetShortPathName(path, short_buf, short_length) 
    # Next convert the short path back to a long path 
    long_length = GetLongPathName(short_buf, None, 0) 
    long_buf = ctypes.create_string_buffer(long_length) 
    GetLongPathName(short_buf, long_buf, long_length) 
    return long_buf.value 
+0

Điều này làm việc tuyệt vời NGOẠI TRỪ rằng ổ đĩa hoặc thành phần mạng của một đường dẫn vẫn có thể là một trường hợp tùy ý. Tôi thấy hữu ích khi thêm 'parts = os.path.splitdrive (os.path.normcase (đường dẫn))' 'path = parts [0] .upper() + parts [1]' vào đầu để tôi có các ký tự ổ chữ hoa và đường dẫn mạng chữ thường. – garlon4

+0

Lưu ý: Đối với giải pháp phụ thuộc hệ thống tệp này trước tiên hãy kiểm tra xem ** tên tập tin ngắn ** được tắt trên ổ đĩa Windows ('fsutil.exe 8dot3name truy vấn C:') - trong khi đó được đề xuất cho hiệu suất trừ khi ứng dụng 16bit vẫn còn ăn. – kxr

1

Sử dụng lib tiêu chuẩn duy nhất, chương trình này hoạt động trên tất cả các con đường phụ tùng/subdirs (trừ ký tự ổ đĩa):

def casedpath(path): 
    r = glob.glob(re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', path)) 
    return r and r[0] or path 

Và cái này xử lý đường dẫn UNC ngoài:

def casedpath_unc(path): 
    unc, p = os.path.splitunc(path) 
    r = glob.glob(unc + re.sub(r'([^:/\\])(?=[/\\]|$)', r'[\1]', p)) 
    return r and r[0] or path 
+0

@Alecz, tệp là trường hợp sử dụng chính. Không thể tạo lại sự cố. Thí dụ? Được biết: Nó không viết hoa chữ cái ổ đĩa có thể (và tên dịch vụ UNC); không chuyển đổi dấu gạch chéo -> dấu gạch chéo ngược. nó không làm bất cứ điều gì trên các tập tin/dirs mà không thực sự tồn tại ngay bây giờ (sự tồn tại của con đường chỉ là một phần). Hoặc có thể bạn đã sử dụng một đường dẫn thử nghiệm với giả mạo/thiếu dấu gạch chéo ngược hoặc thiếu tiền tố chuỗi thô r - ví dụ: '" một số \\ sai \ rawpath.txt "'. – kxr

+0

Tôi không còn có thể tái tạo điều này nữa. Nó hoạt động hoàn hảo, tôi nghĩ rằng đây là một giải pháp rất gọn gàng. Tôi sẽ xóa nhận xét khác của tôi. Cảm ơn! – Alecz