Làm cách nào tôi có thể truy xuất tên tệp tuyệt đối trong tập lệnh shell trên Mac OS X?


19

Tôi muốn lấy tên tệp tuyệt đối của tệp tập lệnh hiện đang được thực thi. Liên kết nên được giải quyết, quá.

Trên Linux, điều này dường như được thực hiện như thế này:

$(readlink -mn "$0")

nhưng readlinkdường như hoạt động rất khác nhau trên Mac OS X.

Tôi đã đọc rằng điều này được thực hiện bằng cách sử dụng

$(realpath $0)

trong BSD nhưng điều đó cũng không hoạt động. Mac OS X không có realpath.

Bất kỳ ý tưởng?


1
Xem câu hỏi này trên SO: stackoverflow.com/questions/799679/ từ
Telemachus


Thậm chí nhiều tùy chọn: stackoverflow.com/questions/7665/ Mạnh
Gerhard Burger

Câu trả lời:


19

Tôi gian lận và sử dụng perl cho chính điều này:

#!/bin/bash
dirname=`perl -e 'use Cwd "abs_path";print abs_path(shift)' $0`
echo $dirname

Bạn sẽ nghĩ rằng tôi chỉ viết toàn bộ kịch bản bằng perl, và tôi thường làm vậy, nhưng không phải lúc nào cũng vậy.


Điều này làm việc, cảm ơn rất nhiều. Tôi sẽ cung cấp cho bạn một upvote ngay khi tôi có thể. Có ai có một cách "vỏ tinh khiết" để làm điều này?
Huxi

1
Tôi sợ điều này là tốt như nó được. (Với nhiều bản hack "vỏ nguyên chất" nhiều dòng có thể tìm thấy trên Google.)
Arjan

một khả năng khác (mặc dù xấu) là đi qua đường dẫn '..', ghi nhớ (thông qua đệ quy hoặc một mảng) cho đến khi '..' trả về cùng một tệp bạn vừa có (ví dụ: bạn ở trên cùng), sau đó quay lại lắp ráp con đường khi bạn đi Tôi đã thấy phần mềm sao lưu Networker của Legato thực hiện điều này trong giai đoạn như một phương pháp để có được đường dẫn 'đúng' (nhưng có lẽ không tuyệt đối). Nhưng nó sẽ là nhiều mã hơn nhiều so với ở trên.
ericslaw

Không chắc chắn tại sao ai đó sửa đổi mã để sử dụng $ 1 thay vì $ 0. Không phải $ 1 là đối số đầu tiên của tập lệnh bash sao? Tôi muốn đường dẫn đến tập lệnh bash thực thi, không phải là đối số đầu tiên.
ericslaw

27
#!/usr/bin/env bash
scriptDir="$(cd "$(dirname "$0")" && pwd -P)"

Hoạt động trong MacOSX cũng vậy.
Alexar

1
Đây là một siêu nhân! Có rất nhiều câu trả lời quá phức tạp khác trôi nổi xung quanh.
Jason S

3
Điều này chỉ hoạt động cho các tệp trong một thư mục được liên kết với nhau, không phải cho các tệp được liên kết chung nói chung
Gerhard Burger

1
Nó cũng hữu ích để unset -v CDPATHtrước cd vì cd có thể gây ra đầu ra không mong muốn nếu CDPATH được đặt.
Nhị phân Phile

Để xử lý ít nhất một lớp liên kết tượng trưng của tệp, bạn cũng có thể kiểm tra theo cách tương thích với đường dẫn đọc (mac không có -f): scriptDir=$(unset -v CDPATH; cd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE)")" && pwd -P)
Binary Phile

0

Điều này xử lý các combo liên kết tượng trưng và nó hoạt động trên các tệp và thư mục:

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

Nhưng nó không hỗ trợ - liên quan đến. Điều này sẽ yêu cầu chuyển đổi được mô tả ở đây .


0

Cách tiếp cận khác:

# Install.
brew install coreutils

# Use the GNU variant.
grealpath --help
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.