2009-01-07 21 views
10

Điều tôi muốn làm là bao gồm cài đặt từ tệp vào vỏ bash tương tác hiện tại của tôi như sau:Làm thế nào một tập lệnh bash có thể biết được thư mục mà nó được cài đặt khi nó có nguồn gốc. nhà điều hành?

$. /path/to/some/dir/.settings

Vấn đề là tập lệnh .settings cũng cần sử dụng "." toán tử bao gồm các tệp khác như sau:

. .extra_settings

Làm cách nào để tham chiếu đường dẫn tương đối cho tệp .extra_settings trong tệp .settings? Hai tệp này luôn được lưu trữ trong cùng một thư mục, nhưng đường dẫn đến thư mục này sẽ khác nhau tùy thuộc vào nơi các tệp này được cài đặt.

Toán tử luôn biết/path/to/some/dir/như được hiển thị ở trên. Làm thế nào có thể các tập tin .settings biết thư mục mà nó được cài đặt? Tôi không muốn có một quá trình cài đặt ghi lại tên của thư mục được cài đặt.

Trả lời

17

Tôi tin $(dirname "$BASH_SOURCE") sẽ làm những gì bạn muốn, miễn là các tập tin bạn đang tìm nguồn cung ứng là không một liên kết tượng trưng.

Nếu tập tin bạn đang tìm nguồn cung ứng có thể là một liên kết tượng trưng, ​​bạn có thể làm điều gì đó như sau để có được những thư mục đúng:

PRG="$BASH_SOURCE" 
progname=`basename "$BASH_SOURCE"` 

while [ -h "$PRG" ] ; do 
    ls=`ls -ld "$PRG"` 
    link=`expr "$ls" : '.*-> \(.*\)$'` 
    if expr "$link" : '/.*' > /dev/null; then 
     PRG="$link" 
    else 
     PRG=`dirname "$PRG"`"/$link" 
    fi 
done 

dir=$(dirname "$PRG") 
+0

Hoàn hảo. $ (dirname "$ BASH_SOURCE") là những gì tôi đã chính xác những gì tôi đang tìm kiếm. Vì mục đích của tôi, tôi không quan tâm nhiều đến symlink. Cám ơn vì đã hồi âm. Câu trả lời thực sự tốt ở đây. – Gary

+8

Để giải quyết các liên kết tượng trưng bạn có thể làm: 'dir = $ (dirname $ (readlink -f" $ BASH_SOURCE "))' –

0

Tôi đã cố gắng gây rối với các biến thể $ (dirname $ 0) nhưng không thành công khi tệp .settings được bao gồm với ".". Nếu tôi đang thực thi tệp .settings thay vì bao gồm nó, giải pháp này sẽ hoạt động. Thay vào đó, $ (dirname $ 0) luôn trả về ".", Nghĩa là thư mục hiện hành. Điều này không thành công khi thực hiện một việc như sau:

$ cd/ $. /some/path/.settings

+0

hmm, quá tệ. Tôi không có ý tưởng sau đó –

2

Một sự cố khác về vấn đề này - nếu bạn đang sử dụng "." để thiết lập biến môi trường, một cách tiêu chuẩn để làm điều này là phải có kịch bản của bạn vang lệnh thiết lập biến, ví dụ:

# settings.sh 
echo export CLASSPATH=${CLASSPATH}:/foo/bar 

sau đó eval đầu ra:

eval $(/path/to/settings.sh) 

Đó là cách gói như modules công việc . Bằng cách này cũng giúp bạn dễ dàng hỗ trợ vỏ có nguồn gốc từ sh (X=...; export X) và csh (setenv X ...)

+0

Phải, đó là cách INN làm điều đó. "innconfvar" (tôi nghĩ đó là những gì nó được gọi) phát ra các biến cấu hình như sh, csh hoặc lệnh perl. –

+0

Tôi thích ý tưởng này. Tuy nhiên, tôi không sử dụng nó bởi vì các tác dụng phụ sẽ làm cho tập tin .settings thậm chí còn khó đọc hơn vì nó đã có rất nhiều lối thoát để bắt đầu. Xem bên dưới. – Gary

0

này loại công trình. Nó hoạt động theo nghĩa là bạn có thể sử dụng cú pháp $ (dirname $ 0) trong tệp .settings để xác định nhà của nó vì bạn đang thực thi tập lệnh này trong một trình bao mới. Tuy nhiên, nó bổ sung thêm thêm một lớp chập nơi bạn cần thay đổi dòng như:

export MYDATE=$(date) 

để

echo "export MYDATE=\$(date)" 

Có lẽ đây là cách duy nhất?

+0

Dường như nó cũng sẽ thêm độ phức tạp nếu bạn tìm nguồn cung ứng trong các hàm hệ vỏ. (Tôi đang tìm cách để làm điều này hoạt động với cả ksh và bash ...) – mpontillo

6

Đây là những gì có thể là một giải pháp thanh lịch:

script_dir=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) 

này sẽ không, tuy nhiên, công việc khi tìm nguồn cung ứng liên kết.Trong trường hợp đó, một người có thể làm

script_dir=$(readlink -f $(readlink "${BASH_SOURCE[0]}") 

Hãy lưu trữ các mảng như ${array[x]} không tuân thủ POSIX. Tất nhiên, mảng BASH_SOURCE chỉ có sẵn trong Bash.

+0

Tại sao '[0]' lại cần thiết? @JasonDay không có nó trong câu trả lời của anh ấy. – asmeurer

+3

BASH_SOURCE là một mảng đại diện cho ngăn xếp cuộc gọi với phần tử đầu tiên là tập lệnh hiện đang thực thi. –

Các vấn đề liên quan