Cách lấy phần cuối cùng của dirname trong Bash


81

Giả sử tôi có một tập tin /from/here/to/there.txt, và muốn nhận được chỉ là phần cuối cùng của dirname của nó tothay vì /from/here/to, những gì tôi nên làm gì?

Câu trả lời:


120

Bạn có thể sử dụng basenamemặc dù nó không phải là một tệp. Loại bỏ tên tệp bằng cách sử dụng dirname, sau đó sử dụng basenameđể lấy phần tử cuối cùng của chuỗi:

dir="/from/here/to/there.txt"
dir="$(dirname $dir)"   # Returns "/from/here/to"
dir="$(basename $dir)"  # Returns just "to"

2
lệnh '$ dir = "$ (dirname $ dir)"' không hoạt động với tôi, nhưng 'dir = "$ (dirname $ dir)"' hoạt động tốt.
Nikolai Saiko

2
Tôi không nên có đô la trước dirkhi tôi đặt nó.
David W.

26

Ngược lại với dirnamebasename:

basename "$(dirname "/from/here/to/there.txt")"

23

Sử dụng bashcác hàm chuỗi:

$ s="/from/here/to/there.txt"
$ s="${s%/*}" && echo "${s##*/}"
to

9

Sử dụng mở rộng tham số Bash , bạn có thể làm điều này:

path="/from/here/to/there.txt"
dir="${path%/*}"       # sets dir      to '/from/here/to' (equivalent of dirname)
last_dir="${dir##*/}"  # sets last_dir to 'to' (equivalent of basename)

Điều này hiệu quả hơn vì không có lệnh bên ngoài nào được sử dụng.


Tôi vừa thử nghiệm cái này. Trên FreeBSD, đây là kết quả của tôi: Mã: #! / Bin / sh cd / var / svn / repos path = "$ 1" echo "$ {path}" dir = "$ {path% / *}" echo "$ {dir } "thực tế =" $ {dir ## * /} "echo" $ {thực tế} "----------------------------- ----------- Kết quả: $ ./makerepo.sh / var / test / var / test / var var $ ------------------- ----------------- Thất bại! Lấy làm tiếc. Có vẻ là một phương pháp tốt nhưng không phải là một câu trả lời chính xác.
Richard Robertson

4

Cách BASH tinh khiết:

s="/from/here/to/there.txt"
[[ "$s" =~ ([^/]+)/[^/]+$ ]] && echo "${BASH_REMATCH[1]}"
to

2
Sẽ không hoạt động nếu tệp không có dấu chấm .. Sẽ không hoạt động nếu thư mục có dấu chấm .. Giữ cho nó đơn giản và sử dụng dấu gạch chéo /làm dấu phân cách.
alvits

1
Cảm ơn rất nhiều @Akshay
anubhava

3

Một awkcách để làm điều đó sẽ là:

awk -F'/' '{print $(NF-1)}' <<< "/from/here/to/there.txt"

Giải trình:

  • -F'/' đặt dấu phân tách trường là "/"
  • in trường cuối cùng thứ hai $(NF-1)
  • <<<sử dụng bất kỳ thứ gì sau nó làm đầu vào tiêu chuẩn ( wiki giải thích )

2

Một cách nữa

IFS=/ read -ra x <<<"/from/here/to/there.txt" && printf "%s\n" "${x[-2]}"

Đơn giản để sử dụng: printf "%s\n" "${x[-2]}".
gniourf_gniourf

1

Câu hỏi này là một cái gì đó như thế này .

Để giải quyết điều đó bạn có thể làm:

DirPath="/from/here/to/there.txt"
DirPath="$(dirname $DirPath)"
DirPath="$(basename $DirPath)"

echo "$DirPath"

Như bạn tôi đã nói điều này cũng có thể xảy ra:

basename `dirname "/from/here/to/there.txt"`

Để có được bất kỳ phần nào của con đường của bạn, bạn có thể làm:

echo "/from/here/to/there.txt" | awk -F/ '{ print $2 }'
OR
echo "/from/here/to/there.txt" | awk -F/ '{ print $3 }'
OR
etc

1

Câu trả lời hàng đầu là hoàn toàn chính xác cho câu hỏi được đặt ra. Trong một trường hợp chung chung hơn với thư mục cần thiết nằm giữa một đường dẫn dài, cách tiếp cận này dẫn đến một đoạn mã khó đọc. Ví dụ :

dir="/very/long/path/where/THIS/needs/to/be/extracted/text.txt"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(dirname $dir)"
dir="$(basename $dir)"

Trong trường hợp này, người ta có thể sử dụng:

IFS=/; set -- "/very/long/path/where/THIS/needs/to/be/extracted/text.txt"; set $1; echo $6
THIS
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.