Nhận đường dẫn của tập lệnh hiện tại khi được thực thi thông qua một liên kết tượng trưng


59

Tôi có một tiện ích bao gồm một vài thư mục với một số tập lệnh bash và các tệp hỗ trợ sẽ được triển khai cho một số máy có thể trong một thư mục khác nhau trên mỗi máy. Các tập lệnh cần có khả năng tham chiếu các đường dẫn liên quan đến chính chúng vì vậy tôi cần có thể có được đường dẫn đến tệp hiện đang được thực thi.

Tôi nhận thức được dirname $0thành ngữ hoạt động hoàn hảo khi tập lệnh của tôi được gọi trực tiếp. Thật không may, có một mong muốn có thể tạo ra các liên kết tượng trưng cho các tập lệnh này từ một thư mục hoàn toàn khác và vẫn có công việc logic đường dẫn tương đối.

Một ví dụ về cấu trúc khô tổng thể như sau:

/
 |-usr/local/lib
 |  |-foo
 |  |  |-bin
 |  |  |  |-script.sh
 |  |  |-res
 |  |  |  |-resource_file.txt
 |-home/mike/bin
 |  |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)

Làm thế nào tôi có thể tham khảo đáng tin cậy /usr/local/lib/foo/res/resource_file.txttừ script.shviệc nó được gọi bởi /usr/local/lib/foo/bin/script.shhay ~mike/bin/link_to_script?

Câu trả lời:


80

Hãy thử điều này như một giải pháp cho mục đích chung:

DIR="$(cd "$(dirname "$0")" && pwd)"

Trong trường hợp cụ thể của các liên kết tượng trưng sau đây, bạn cũng có thể làm điều này:

DIR="$(dirname "$(readlink -f "$0")")"

Hoạt động hoàn hảo và đơn giản hơn những thứ tôi đang thử. Cảm ơn!
Mike Deck

@MikeDeck Thưởng thức. Lưu ý rằng tôi đã sửa một số vấn đề trích dẫn kể từ lần đăng đầu tiên ... đôi khi bạn có thể sử dụng một tùy chọn từ chỉnh sửa mới nhất trong trường hợp bạn có khoảng trắng hoặc các ký tự lập dị khác trong đường dẫn của bạn. Ngay cả khi nó không quan trọng đối với dự án này, bạn có thể sao chép mã từ các tập lệnh của riêng bạn và có tùy chọn tốt nhất là vấn đề sau đó!
Caleb

1
Tôi nên làm rõ, cái thứ hai hoạt động hoàn hảo. Giải pháp đầu tiên bạn đưa ra không hoạt động đối với các liên kết tượng trưng trên hệ thống của tôi.
Mike Deck

4
@MikeDeck: Giải pháp đầu tiên hoạt động cho trường hợp điển hình là có nhiều thư mục được liên kết với nhau như một phần của đường dẫn, nhưng sẽ không giúp ích nếu nhị phân cuối cùng là một liên kết tượng trưng. Đó là những gì người thứ hai quản lý để chăm sóc.
Caleb

1
Không hoạt động nếu tệp tập lệnh là sourced (ví dụ $ source ./sript.sh) Điều này hoạt động cho cả hai trường hợp:DIR="$(cd "$(dirname "$BASH_SOURCE")" && pwd)"
FractalSpace

7

một đường thẳng:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

2
Câu trả lời một dòng thường không hữu ích nhất. Vui lòng xem xét mở rộng câu trả lời của bạn để bao gồm giải thích, liên kết hoặc tài liệu hỗ trợ thêm cho giải pháp được đề xuất của bạn.
HalosGhost

1
thực tế, bạn không cần phải làm điều này, phiên bản readlink của câu trả lời ban đầu chỉ hoạt động tốt nếu không có liên kết tượng trưng nào cả
THESorcerer 16/2/2016

3

readlink -f không làm việc cho tôi, tôi đã nhầm lẫn này:

readlink: illegal option -- f
usage: readlink [-n] [file ...]

Nhưng điều này hoạt động tốt:

DIR="$(dirname "$(readlink "$0")")"
echo $DIR

3
Sau đó, bạn đang ở trên máy Mac và điều này sẽ trả lời câu hỏi của bạn .
Isaac

Có, tôi đang dùng MacOs @isaac, nhưng tôi không có câu hỏi nào. Tôi đã đăng lệnh hoạt động về phía tôi.
Kevin Campion

0

Một bổ sung nhỏ cho kịch bản trên. Tùy chọn -P để pwd theo các liên kết tượng trưng

DIR="$(cd "$(dirname "$0")" && pwd -P)"

7
Điều này chỉ hoạt động khi symlink là một phần của cấu trúc thư mục. Nó không hoạt động khi tập tin được liên kết.
Oliver Gondža
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.