Tại sao tôi cần phải nhập `. /` Trước khi thực hiện một chương trình trong thư mục hiện tại?


92

Trong khi thực hiện chương trình C a.out, sử dụng thiết bị đầu cuối Ubuntu, tại sao tôi luôn cần phải gõ ./trước đó a.out, thay vì chỉ viết a.out? Có giải pháp cho việc này?




Câu trả lời:


119

Khi bạn nhập tên của một chương trình, chẳng hạn như a.outhệ thống sẽ tìm tệp trong PATH của bạn. Trên hệ thống của tôi, PATH được đặt thành

/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Có lẽ bạn cũng tương tự. Để kiểm tra, nhập echo $PATHvào một thiết bị đầu cuối.

Hệ thống xem qua các thư mục này theo thứ tự cho trước và nếu không thể tìm thấy chương trình sẽ tạo ra command not foundlỗi.

Chuẩn bị lệnh với ./hiệu quả là "hãy quên PATH, tôi muốn bạn chỉ nhìn trong thư mục hiện tại".

Tương tự, bạn có thể yêu cầu hệ thống chỉ nhìn vào một vị trí cụ thể khác bằng cách thêm lệnh bằng một đường dẫn tương đối hoặc tuyệt đối, chẳng hạn như:

../có nghĩa là trong thư mục cha, ví dụ như ../hellotìm lời chào trong thư mục cha.

./Debug/hello: "tìm kiếm hellotrong thư mục con Debug của thư mục hiện tại của tôi."

hoặc /bin/ls: "tìm lstrong thư mục /bin"

Theo mặc định, thư mục hiện tại không nằm trong đường dẫn vì nó được coi là rủi ro bảo mật. Xem tại sao là. không theo đường dẫn theo mặc định? trên Superuser tại sao.

Có thể thêm thư mục hiện tại vào PATH của bạn, nhưng vì những lý do được đưa ra trong câu hỏi được liên kết, tôi không khuyến nghị.


25
Điều này. +1 Không thêm .vào của bạn PATH(như 2 câu trả lời khác hiện đang đề xuất) do rủi ro bảo mật được đề cập trong câu trả lời này.
Ngày

8
Nó cũng có thể đáng chú ý là không có gì đặc biệt về là .ở đây, bạn có thể sử dụng một đường dẫn đầy đủ hoặc tương đối so với một ví dụ thực thi /home/user/foo/a.outhay./build/a.out
tobyodavies

@tobyodavies; Trên thực tế .là đặc biệt bởi vì nó có nghĩa là "thư mục hiện tại của tôi" vì vậy có thể là bất kỳ thư mục nào mà người dùng tự tìm thấy chúng với các đặc quyền đọc và thực thi. Điều này có khả năng nguy hiểm hơn là thêm một đường dẫn đủ điều kiện cụ thể.
Warren Hill

@WarrenHill khi xem xét thêm nó vào con đường của bạn, vâng nó khá khác biệt. Tuy nhiên, về mặt cú pháp bash, .không có trạng thái đặc biệt, đó chỉ là một đường dẫn có thể bắt đầu bằng /./blahsẽ hoạt động tốt với cathoặc grepnhư một dấu nhắc bash.
tobyodavies

@tobyodavies: OK Tôi đã chỉnh sửa câu trả lời của mình để đưa vào quan điểm của bạn.
Warren Hill

24

Lý do cho điều này là đơn giản.

Giả sử bạn có một lệnh có cùng tên với một ứng dụng trong thư mục hiện tại. Sau đó, chạy lệnh trong trình bao sẽ gọi ứng dụng của bạn thay vì lệnh tích hợp. Đây sẽ là một mối quan tâm an ninh nếu không có gì khác.

Bằng cách yêu cầu ./được sử dụng ở phía trước, shell biết rằng bạn muốn thực thi ứng dụng với tên đã cho và không phải là lệnh tích hợp có tên đó.


1
giải thích của bạn là sai lệch, có một sự khác biệt giữa các lệnh tích hợp trong trình bao và các tệp thực thi có thể truy cập thông qua biến PATH. Vì thực tế câu trả lời của bạn càng đọc tôi càng cảm thấy không chính xác.
Ahmed Masud

16

./thực thi các tệp không nằm trong tệp của bạn $PATH, thay vào đó, nó thực thi tệp trong thư mục hiện tại (hoặc thông qua tệp khác ./home/stefano/script.sh). Bây giờ, PATH là một biến môi trường chứa tất cả các vị trí mà bash có thể tìm kiếm các chương trình thực thi mà không có đường dẫn đầy đủ (tuyệt đối) đến chúng.

Sự tách biệt này là cần thiết để tránh chạy sai tệp. Tức là nếu bạn có một tập tin được gọi lstrong thư mục nhà của bạn, nó không có trong PATH của bạn sẽ ngăn bash nhầm lẫn nó với thực tế ls. Biến PATH cũng xác định thứ tự tìm kiếm:

  • Khi bạn chạy một lệnh hoặc một chương trình cố gắng tạo một exectòa nhà (một phương thức đặc biệt của Kernel, cách các chương trình được bắt đầu), hệ thống sẽ tìm tệp bằng cách đi qua từng thư mục trong PATH của bạn. Khi chương trình đã được tìm thấy, ngay cả khi nó nằm trong nhiều thư mục, tìm kiếm bị gián đoạn và tìm kiếm đầu tiên được chạy.

Để chạy một tệp, bạn sẽ cần đặt bit thực thi trong các quyền:

  • Vì bạn đã ở trên dòng lệnh, bạn chỉ cần gõ chmod +x finename.

  • Hoặc bạn có thể đặt quyền bằng cách nhấp chuột phải vào tệp và chọn Thuộc tính :

    văn bản thay thế

Bây giờ bạn có thể sao chép tệp vào bất kỳ thư mục nào trong PATH, để xem những thư mục nào trong đó - và chúng được đặt trên cơ sở cho mỗi người dùng - loại echo $PATH.

stefano@3000-G530:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Nếu bạn tạo một tập tin thực thi, catvà di chuyển nó đến /usr/local/sbin, nó được chạy thay vì thích cat, mà nằm trong /bin. Bạn có thể tìm ra nơi tập tin của bạn bằng cách sử dụng type catwhereis cat.


2
Một điều cần lưu ý: câu hỏi của anh ta dường như chỉ ra rằng anh ta đã biên dịch và liên kết một cái gì đó với gcc, nó tự động thiết lập bit thực thi.
Nathan Osman

12

Tại sao bạn cần gõ ./trước khi thực hiện một chương trình?

Trong thiết bị đầu cuối, bất cứ khi nào bạn nhập tên của một ứng dụng, giả sử gedit, thiết bị đầu cuối sẽ tìm trong một số thư mục (được xác định trước) có chứa các ứng dụng (nhị phân của ứng dụng). Tên của các thư mục này được chứa trong một biến được gọi PATH. Bạn có thể thấy những gì trong biến này bằng cách thực hiện echo $PATH. Xem những thư mục được phân cách bởi :? Đó là những thư mục mà các thiết bị đầu cuối sẽ đi tìm kiếm trong, nếu bạn chỉ cần gõ gedit, nautilushoặc a.out. Như bạn có thể thấy, đường dẫn của a.outchương trình của bạn không có ở đó. Khi bạn làm như vậy ./a.out, bạn đang nói với thiết bị đầu cuối "hãy tìm trong thư mục hiện tại và chạy a.out, và đừng đi tìm PATH.

Giải pháp 1

Nếu bạn không muốn nhập ./mỗi lần, bạn sẽ cần thêm a.outthư mục của $PATH. Trong các hướng dẫn sau, tôi sẽ cho rằng đường dẫn đến a.out/path/to/programs/, nhưng bạn nên thay đổi nó thành đường dẫn thực tế của mình.

  1. Chỉ cần thêm dòng sau vào cuối tệp ~/.pam_environment:

    PATH DEFAULT=${PATH}:/path/to/programs

    Nguồn: Biến môi trường liên tục

  2. Đăng xuất và đăng nhập lại. Bây giờ bạn có thể chạy a.outmà không cần ./từ bất kỳ thư mục nào.

Nếu bạn có các chương trình khác trong các thư mục khác, bạn chỉ có thể thêm chúng vào dòng trên. Tuy nhiên, tôi khuyên bạn nên có một thư mục gọi là "myPrograms" và đặt tất cả các chương trình của bạn vào đó.

Giải pháp 2

Lưu ý: thay đổi userNametên người dùng Ubuntu thực tế của bạn.

Nếu bạn có các chương trình khác mà bạn muốn chạy thì sao? Và tất cả chúng trong các thư mục khác nhau? Chà, một giải pháp "có tổ chức hơn" sẽ là tạo một thư mục được gọi bintrong thư mục Home của bạn và thêm các liên kết tượng trưng (phím tắt) trong thư mục đó. Đây là cách thực hiện:

  1. mkdir /home/userName/bin

    • Điều này sẽ tạo thư mục bintrong thư mục Home của bạn.
  2. ln -s /path/to/programs/a.out /home/userName/bin

    • Điều này sẽ tạo ra một "liên kết tượng trưng" (về cơ bản, một phím tắt) của a.outchương trình của bạn theo bin.
  3. Đăng xuất và đăng nhập lại. Bây giờ bạn có thể chạy a.outmà không cần ./từ bất kỳ thư mục nào.

Bây giờ, bất cứ khi nào bạn có một chương trình khác ở bất kỳ nơi nào khác, hãy giả sử chương trình b.intrên Máy tính để bàn của bạn, tất cả những gì bạn cần làm là : ln -s /home/userName/Desktop/b.in /home/userName/bin, và sau đó bạn sẽ có thể chạy chương trình đó mà không cần ./.

Lưu ý: nhờ nhận xét của @ Joe , khi bạn thực hiện sao lưu, các liên kết tượng trưng phải được xử lý đặc biệt. Theo mặc định, rsynchoàn toàn không xử lý chúng, vì vậy khi bạn khôi phục, chúng không ở đó.


1
Đây là một mẹo hữu ích nếu nó được sử dụng một cách tiết kiệm. Sử dụng nó rất nhiều làm cho hệ thống của bạn làm những điều mà người khác không mong đợi. Ngoài ra, khi bạn thực hiện sao lưu, các liên kết tượng trưng phải được xử lý đặc biệt. Theo mặc định , rsync hoàn toàn không xử lý chúng, vì vậy khi bạn khôi phục chúng không có ở đó.
Joe

1

Như George đã chỉ ra trong câu trả lời của mình, điều này giúp bạn lưu ý rằng việc bạn thực thi một tệp trong thư mục làm việc hiện tại ( pwd).

Tôi nhớ đã hỏi câu hỏi này với tiền bối của tôi từ lâu, anh ấy nói tôi nên thêm .vào đường dẫn của mình để khi tôi thực hiện a.outnó trong thư mục hiện tại và thực hiện điều đó. Trong trường hợp này tôi không phải làm ./a.out.

Nhưng, cá nhân, tôi khuyên bạn nên chống lại nó. Điều đó không bao giờ xảy ra với tôi, nhưng nếu bạn đang ở trong một thư mục mạng của người ngoài hành tinh hoặc một cái gì đó, và một tập tin thực thi độc hại được gọi là lstồn tại ở đó, thì có .trong đường dẫn của bạn là một ý tưởng rất tồi. Không phải là bạn sẽ gặp vấn đề này rất thường xuyên, chỉ cần nói.


ok, Stefano đã thông qua câu trả lời của mình để chứa thông tin này :)
Shrikant Sharat

3
Tôi hoàn toàn đồng ý với việc không thêm .vào $PATH. Ý tưởng rất nguy hiểm.
Nathan Osman

1

Ngoài các câu trả lời khác, đây là phần thiết yếu man bashđể giải thích điều đó:

THỰC HÀNH
       Sau khi một lệnh đã được chia thành các từ, nếu nó dẫn đến một đơn giản
       lệnh và một danh sách tùy chọn của các đối số, các hành động sau đây là
       Lấy.

       Nếu tên lệnh không chứa dấu gạch chéo, shell sẽ cố định vị
       nó Nếu tồn tại một hàm shell theo tên đó, thì hàm đó là
       được gọi như mô tả ở trên trong CHỨC NĂNG. Nếu tên không khớp với
       Hàm, shell tìm kiếm nó trong danh sách các nội trang shell. Nếu như
       một trận đấu được tìm thấy, nội dung đó được gọi.

       Nếu tên không phải là hàm shell cũng không phải là hàm dựng và không chứa
       dấu gạch chéo, bash tìm kiếm từng phần tử của PATH cho một thư mục con‐
       xé một tập tin thực thi bằng tên đó.

0

Một './' có ý nghĩa khi bạn chạy một chương trình được biết đến với bạn và cụ thể, ví dụ như chương trình của riêng bạn. Chương trình này phải có mặt trong thư mục hiện tại của bạn. Một './' không có nghĩa gì khi bạn chạy một lệnh tiêu chuẩn nằm ở đâu đó trong $ PATH. Lệnh "lệnh chạy nào" cho bạn biết lệnh chạy ở đâu trong $ PATH.


0
$ gcc hello.c -o /path/to/someplace/hello

sẽ tạo ra một thực thi tại một số vị trí. Nếu vị trí đó nằm trên đường dẫn của bạn, bạn sẽ có thể chạy tệp. Bạn có thể viết kịch bản này nếu bạn muốn tạo nhãn cho hành động "biên dịch mã nguồn này bằng gcc và đặt tệp thực thi tại một số vị trí trên đường dẫn của bạn"

Tôi sẽ đề nghị bạn tạo một thư mục mới gọi là "testbin" hoặc một cái gì đó thuộc loại đó và đặt nó trên đường dẫn của bạn để giữ cho các thư mục đường dẫn hiện tại của bạn sạch sẽ.


0

./loại bỏ tìm kiếm không cần thiết cho một con đường. ./buộc chỉ tìm kiếm trong thư mục hiện tại Nếu chúng ta không đưa ra ./sau đó nó sẽ tìm kiếm khác nhau con đường đặt vào hệ thống như /usr/bin, /usr/sbin/vv


0

"./" có nghĩa là bạn muốn thực thi một tệp trong thư mục hiện tại, đó là một phím tắt để nhập toàn bộ đường dẫn chẳng hạn:

[root@server ~]#/path/to/file/file.pl

giống như:

[root@server file]#./file.pl

trong ví dụ trước bạn đã đi qua thư mục và siêu thư mục của nó đến vị trí tệp và sử dụng "./" để chạy tệp trong thư mục hiện tại.

cái trước nó " [root @ server ~] # / path / to / file / file.pl " cũng sẽ thực thi tệp nếu bạn lười "cd" theo cách của bạn đến vị trí tệp.


-4

Nó rất đơn giản và có nhiều công dụng.

  1. Khi nhiều phiên bản của cùng một ứng dụng được cài đặt, nó sẽ có sẵn trong đường dẫn khác nhau nhưng có thể tạo một liên kết mềm đến nhị phân của bạn /usr/bin. Ví dụ: Python 2.7, Python 2.6 được cài đặt nhưng / usr / bin / python -> python2.7 / usr / local / bin / python -> python2.6

Nếu bạn đang ở trong đường dẫn /usr/local/binvà thực thi Python, nó sẽ luôn thực thi Python 2.7. Chỉ định .sẽ lấy thực thi của thư mục hiện tại.

  1. .- luôn đại diện thực hiện từ thư mục hiện tại. Và ..luôn luôn có nghĩa là thực thi từ thư mục trước.
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.