Làm thế nào để Linux xử lý nhiều dấu tách đường dẫn liên tiếp (tập tin / home //// tên người dùng ///)?


111

Tôi đang làm việc với một kịch bản python chuyển các vị trí tệp đến một quy trình con scp. Điều đó không sao, nhưng tôi đang ở trong một tình huống mà cuối cùng tôi có thể nối một đường dẫn với một tên tệp sao cho có một dấu hai ' /trong đường dẫn. Tôi biết rằng bash không quan tâm nếu bạn có nhiều trình phân tách tệp, nhưng tôi tự hỏi làm thế nào chính xác điều đó được khắc phục. Là bash mà dải thêm /s hoặc nó thực sự không quan trọng bao giờ?

Tôi yêu cầu bởi vì nó sẽ tiết kiệm cho tôi một vài dòng mã để kiểm tra thêm /s trong khi nối. Tôi biết đó không phải là một vấn đề lớn, nhưng tôi cũng tò mò. Tôi có một tập lệnh bash có dòng cd //usr(thay vì cd /usr), dường như ngụ ý có thể có một ý nghĩa đối với việc sử dụng nhiều /s trong một đường dẫn


7
Tôi sẽ đầu tư vào các dòng mã bổ sung ...
Stefan

5
Chỉ trong trường hợp bất cứ ai quan tâm, mà tôi chắc chắn rằng không ai làm, tôi đã làm trong thực tế kết thúc bằng cách sử dụng python joinabspathvà các lệnh như vậy.
Falmarri

Câu trả lời:


165

Nhiều dấu gạch chéo được phép và tương đương với một dấu gạch chéo. Từ đặc tả Unix đơn (phiên bản 3) , các định nghĩa cơ sở §3.266 tên đường dẫn : Triệu Nhiều dấu gạch chéo liên tiếp được coi là giống như một dấu gạch chéo.

Có một ngoại lệ: nếu một tên đường dẫn bắt đầu bằng chính xác hai dấu gạch chéo, nó có thể được xử lý khác nhau (ref: định nghĩa cơ sở §4.11 độ phân giải tên đường dẫn ). Bản thân Linux không làm điều này, mặc dù một số ứng dụng có thể và các hệ thống unix-ish khác làm (ví dụ Cygwin).

Một dấu /ở cuối tên đường dẫn buộc tên đường dẫn phải tham chiếu đến một thư mục. Trong ( POSIX định nghĩa 1.003,1-2001 (Single Unix v3) cơ sở giải quyết §4.11 tên đường dẫn , một dấu /tương đương với một dấu /.. POSIX 1.003,1-2008 (Single Unix định nghĩa v4) cơ sở §4.12 loại bỏ các yêu cầu để làm cho nó tương đương với /., để để đối phó với các thư mục không tồn tại (ví dụ: mkdir foo/bắt buộc phải hoạt động, trong khi mkdir foo/.sẽ không - xem cơ sở lý luận cho sự thay đổi).

Đối với các chương trình hoạt động trên một mục nhập thư mục, nếu foolà một liên kết tượng trưng đến một thư mục, thì việc truyền foo/là một cách để làm cho chương trình hoạt động trên thư mục thay vì liên kết tượng trưng.

¹ Lưu ý rằng đây áp dụng cho chỉ có độ phân giải tên đường dẫn, tức là khi truy cập vào tập tin. Thao tác tên tệp có thể hoạt động khác nhau. Ví dụ basenamedirnamebỏ qua dấu gạch chéo.


7
Tương đương với /.đã bị xóa sau một quá trình thảo luận sau đó vì nó mơ hồ. Dù sao +1 khi tìm thấy loại thông tin này được tóm tắt tốt là khó.
hakre

17

Hệ điều hành dường như cũng không quan tâm đến nó, khi vừa thử một chương trình C với một tòa nhà trực tiếp để mở bằng // trong đường dẫn.

Bạn có thể sử dụng chức năng thư viện python os.path.normpath để bình thường hóa nó, điều này giúp bạn tiết kiệm được việc quét qua chuỗi tìm kiếm các tính năng bổ sung. Các ngôn ngữ khác có chức năng tương tự.

http://docs.python.org/l Library / os.path.html # os.path.normpath


5
Coi chừng nhận xét sau trong nguồn Normpath: Bình thường hóa một đường dẫn, ví dụ A // B, A /./ B và A / foo /../ B đều trở thành A / B. Cần hiểu rằng điều này có thể thay đổi ý nghĩa của đường dẫn nếu nó chứa các liên kết tượng trưng!
Bluehorn

8

Trên tất cả các hệ thống Unix mà tôi đã thấy nó giống như một /, nhưng tiêu chuẩn Unix chỉ định rằng

Một tên đường dẫn bắt đầu bằng hai dấu gạch chéo liên tiếp có thể được diễn giải theo cách được xác định theo cách thực hiện, mặc dù nhiều hơn hai dấu gạch chéo hàng đầu sẽ được coi là một dấu gạch chéo.

vì vậy nó có thể được xử lý đặc biệt, tùy thuộc vào hệ thống của bạn. (Một số phiên bản Unix cũ hơn đã sử dụng một đầu kép /để truy cập hệ thống tệp từ xa và vẫn có thể có một số phiên bản khác .)


7
Cygwin (trong khi không phải là một UNIX thực) sẽ dịch //remote/...sang truy cập hệ thống tệp từ xa, có thể là để thống nhất với Windows ' \\remote\....
ephemient

2
Tôi tin rằng (nhưng không thể google lên một tài liệu tham khảo tốt ngay bây giờ) rằng API compat Windows POSIX cũng sẽ xử lý //remote/...giống như \\remote\...định dạng đường dẫn UNC .
Stephen P

1
Tôi nghĩ rằng tôi nhớ lại rằng các tên đường dẫn di động của Boost.Filesystem xử lý //theo một cách đặc biệt, theo đó chúng có thể kiểm tra tính falsetuyệt đối, tuân thủ thông số Unix / POSIX.

7

Sử dụng os.path.jointrong Python và bạn sẽ không nhận được nhiều dấu gạch chéo. Tự xây dựng tên tập tin bằng cách nối các chuỗi được coi là kiểu Python kém.


Tôi đồng ý, nhưng tên tệp là một phần của chuỗi lệnh và thay vì phân tích chuỗi lệnh để nối vào tên tệp (ở cuối), tôi chỉ muốn nối thêm nó.
Falmarri

1
@Falmarri: Bạn không thể chỉ thêm tên tệp vào chuỗi lệnh! Một chuỗi lệnh sẽ được phân tách bằng shell, vì vậy các ký tự đặc biệt trong tên tệp cần được trích dẫn. Vì vậy, bạn cần phải xây dựng tên tệp, sau đó trích dẫn nó đúng cách để đặt nó vào chuỗi lệnh.
Gilles

Đây là một dự án thực sự cụ thể mà tôi sẽ sử dụng bản thân mình. Tôi có lẽ đã không đủ rõ ràng để biện minh cho việc không mạnh mẽ về điều này. Tôi nhận được chuỗi đường dẫn tệp này từ một lớp cung cấp cho tôi đường dẫn tệp thoát chính xác và như vậy. Và tôi đang nối nó với một đối số dòng lệnh
Falmarri

1
@Falmarri: Vì vậy, hãy sử dụng Normpath để dọn sạch giá trị dòng lệnh mà bạn không kiểm soát, sau đó sử dụng phép nối để đặt chúng lại với nhau.
Neil Mayhew

Đây thực sự là những gì tôi đã làm = \ Tôi không thể xử lý trường hợp đặc biệt khi tôi được cho /rất tốt.
Falmarri

3

Không có sự khác biệt.

Nhiều dấu gạch chéo bị bỏ qua (không có hiệu lực), ví dụ:

ls -al //usr///////bin/sed

7
thể có nếu nó chính xác là hai và lúc đầu; Một tên đường dẫn bắt đầu bằng hai dấu gạch chéo liên tiếp có thể được diễn giải theo cách xác định thực hiện . Trong thực tế tôi nghĩ rằng điều này là đúng và họ chỉ bị bỏ qua
Michael Mrozek

Cảm ơn Chris, tôi đánh giá cao sự làm rõ! (không may là thông tin đăng nhập OpenID không hoạt động với tôi hoặc tôi sẽ bỏ phiếu cho bạn)

@Rob Bạn chưa đăng ký, nhưng vẫn đăng nhập (bạn được theo dõi bởi cookie của mình). Bạn sẽ có thể đăng ký ngay bây giờ để kết nối OpenID với tài khoản của mình, nhưng bạn sẽ có thể bỏ phiếu bằng bất kỳ cách nào
Michael Mrozek

Cảm ơn Michael nhưng "bạn phải đăng nhập hoặc đăng ký để bình chọn". Khi bạn chỉ sử dụng một địa chỉ email và tên, bạn không có đầy đủ đặc quyền. Và vì OpenID đã hết thời gian và tôi không cảm thấy muốn tạo một tài khoản khác, tôi không gặp may. Tôi đoán lỗi của tôi là lười biếng, nhưng tôi đánh giá cao sự giúp đỡ.

0

Tất nhiên bạn có thể bình thường hóa một đường dẫn có nhiều / (dấu gạch chéo) có thể trong đó bằng cách chuyển qua tr -s

NORMALIZED=$(echo "$UNHYGIENIC" | tr -s / /)

... và sau đó sử dụng $NORMALIZED

Tuy nhiên, nó là cần thiết. Như tôi biết, bất kỳ hạt nhân UNIX đúng nào cũng nên bỏ qua các dấu tách đường dẫn đồng thời --- hoặc về mặt khái niệm coi chúng là ... /./...


"nên" -> "không nên".
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.