Khi viết tập lệnh bash, làm thế nào để tôi có được đường dẫn tuyệt đối của vị trí của tệp hiện tại?


15

Giả sử tôi có một tập tin bash được gọi myBash.bash. Nó nằm trong:

/myDirect/myFolder/myBash.bash

Bây giờ tôi muốn sử dụng chuỗi /myDirect/myFolder(vị trí của myBash.bash) bên trong tập lệnh. Có một lệnh tôi có thể sử dụng để tìm vị trí này?

Chỉnh sửa: Ý tưởng là tôi muốn thiết lập một thư mục zip với mã có thể được bắt đầu bằng một tập lệnh bash bên trong tệp zip đó. Tôi biết các đường dẫn tệp tương đối của mã bên trong tệp zip đó, nhưng không phải là các đường dẫn tuyệt đối và tôi cần chúng. Một cách sẽ là mã cứng trong đường dẫn hoặc yêu cầu đường dẫn của tệp được cung cấp dưới dạng một biến. Tuy nhiên, tôi sẽ thấy dễ dàng hơn nếu bash-file có thể tự tìm ra vị trí của nó và sau đó tạo các đường dẫn có liên quan đến tệp khác từ kiến ​​thức về cấu trúc của tệp zip.


3
Điều này có thể phù hợp hơn cho stackoverflow. Kiểm tra các câu hỏi sau: stackoverflow.com/questions/4774054/ Thẻ stackoverflow.com/questions/59895/ .
Sethos II

1
sử dụng như thế nào? xin làm rõ
Sergiy Kolodyazhnyy 17/03/2017

1
@SethosII câu hỏi này hoàn toàn thuộc chủ đề ở đây
Zanna

1
Tôi đã thêm nhiều bối cảnh cho câu hỏi. Tôi nghĩ rằng có thể có một lệnh dễ dàng / rõ ràng để có được đường dẫn tệp của tệp đang thực thi, nhưng có vẻ như câu trả lời ít nhất là không rõ ràng.
dimpol 17/03/2017

3
@Zanna Tôi không nói nó không chính thống, tôi nghĩ nó chỉ phù hợp hơn và như được hiển thị với các liên kết đã được hỏi và trả lời ở đó nhiều lần.
Sethos II

Câu trả lời:


23

Bạn có thể nhận được đường dẫn đầy đủ như:

realpath "$0"

Và như Serg đã chỉ ra, bạn có thể sử dụng dirnameđể loại bỏ tên tệp như thế này

dirname "$(realpath $0)"

hoặc thậm chí tốt hơn để ngăn chặn trích dẫn vụng về và chia tách từ với tên tệp khó:

temp=$( realpath "$0"  ) && dirname "$temp"

Tốt hơn nhiều so với ý tưởng trước đây của tôi là phân tích nó (tôi biết sẽ có cách tốt hơn!)

realpath "$0" | sed 's|\(.*\)/.*|\1|'

Ghi chú

  • realpath trả về đường dẫn thực của tệp
  • $0 là tập tin này (kịch bản)
  • s|old|new|thay thế oldbằngnew
  • \(.*\)/lưu bất kỳ ký tự nào trước /để sau
  • \1 phần lưu

2
+1 để sử dụng $0sedma thuật. Nhưng sedphép thuật nói trên thực sự không cần thiết khi các công cụ như dirnametồn tại
Sergiy Kolodyazhnyy 17/03/2017

2
bạn đã có câu trả lời, hãy sử dụng realpath: realpath "$( dirname $0 )"Cá nhân tôi sẽ sử dụng readlinknhưng đó là tôi:readlink -e $(dirname $0)
Sergiy Kolodyazhnyy 17/03/2017

@Serg: Sẽ không dirname "$(realpath "$0")"tốt hơn sao? Thông thường người ta muốn biết thư mục mẹ của tệp được tham chiếu thay vì thư mục mẹ của liên kết tượng trưng đề cập đến tệp đã nói.
David Foerster

4
@Serg "$(dirname "$(realpath "$0")")"là cách đơn giản nhất. Báo giá bên trong $()công việc như bình thường.
DepressionDaniel

@DepressionDaniel Đã làm một chút nghiên cứu trực tuyến, bạn đã đúng: $()trở thành một subshell sẽ cho phép có trích dẫn bên ngoài. Mặc dù vậy, tôi sẽ không nói điều đó đơn giản, trừ khi người ta nhận ra $()tất cả là các mạng con
Sergiy Kolodyazhnyy 17/03/2017

5

nếu tập lệnh nằm trong đường dẫn của bạn, bạn có thể sử dụng một cái gì đó như

$ myloc=$(dirname "$(which foo.sh)")
$ echo "$myloc"
/path/to/foo.sh

EDIT: sau khi đọc các bình luận từ Serg, đây có thể là một giải pháp chung hoạt động cho dù tập lệnh có nằm trong đường dẫn của bạn hay không.

myloc==$(dirname "$(realpath $0)")
dirname "$myloc"

whichphù hợp hơn khi tập lệnh nằm trong một trong các thư mục là một phần của PATHbiến. Sử dụng $0từ trong một kịch bản, giống như các chương trình của Zanna. Nhưng câu trả lời của bạn là phù hợp vì bạn sử dụng dirnamethay vì nhắn tin sed, do đó +1 cho điều đó
Sergiy Kolodyazhnyy 17/03/2017

5

Câu trả lời được chấp nhận có vẻ hoàn hảo. Đây là một cách khác để làm điều đó:

cd "$(dirname "$0")"
/bin/pwd

/bin/pwdin đường dẫn thực của thư mục, trái ngược với pwdlệnh dựng sẵn.


0
wdir="$PWD"; [ "$PWD" = "/" ] && wdir=""
case "$0" in
  /*) scriptdir="${0}";;
  *) scriptdir="$wdir/${0#./}";;
esac
scriptdir="${scriptdir%/*}"
echo "$scriptdir"

Nó được thực hiện như là tài liệu tham khảo từ kenorbAndro
Không dirname, readlink, realpath, BASH_SOURCE
Tất cả đều builtins

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.