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?
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:
Khi bạn nhập tên của một chương trình, chẳng hạn như a.out
hệ 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 $PATH
và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 found
lỗ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ư ../hello
tìm lời chào trong thư mục cha.
./Debug/hello
: "tìm kiếm hello
trong thư mục con Debug của thư mục hiện tại của tôi."
hoặc /bin/ls
: "tìm ls
trong 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ị.
.
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.
.
ở đâ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.out
hay./build/a.out
.
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ể.
.
không có trạng thái đặc biệt, đó chỉ là một đường dẫn có thể bắt đầu bằng /
và ./blah
sẽ hoạt động tốt với cat
hoặc grep
như một dấu nhắc bash.
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 đó.
./
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 ls
trong 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:
exec
tò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 :
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, cat
và 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 cat
và whereis cat
.
gcc
, nó tự động thiết lập bit thực thi.
./
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
, nautilus
hoặc a.out
. Như bạn có thể thấy, đường dẫn của a.out
chươ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
.
Nếu bạn không muốn nhập ./
mỗi lần, bạn sẽ cần thêm a.out
thư 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
là /path/to/programs/
, nhưng bạn nên thay đổi nó thành đường dẫn thực tế của mình.
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
Đăng xuất và đăng nhập lại. Bây giờ bạn có thể chạy a.out
mà 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 đó.
Lưu ý: thay đổi
userName
tê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 bin
trong 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:
mkdir /home/userName/bin
bin
trong thư mục Home của bạn.ln -s /path/to/programs/a.out /home/userName/bin
a.out
chương trình của bạn theo bin
.Đăng xuất và đăng nhập lại. Bây giờ bạn có thể chạy a.out
mà 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.in
trê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,
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 ở đó.
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.out
nó 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à ls
tồ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.
.
vào $PATH
. Ý tưởng rất nguy hiểm.
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 đó.
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.
$ 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ẽ.
./
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
"./" 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.
Nó rất đơn giản và có nhiều công dụng.
/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.6Nếu bạn đang ở trong đường dẫn /usr/local/bin
và 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.
.
- 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.