cd vào thư mục của một tập tin liên kết tượng trưng


7

Trước khi tôi viết một kịch bản, bất cứ ai cũng biết một cách dễ dàng để làm như sau:

$ pwd
/foo/bar
$ ls -l
lrwxr-xr-x  1 username  admin  48 Apr 17  2012 foo.sh -> /bar/foo.sh
$ cd /bar
$ ls
foo.sh

tức là trong thư mục /foo/bar, tôi muốn làm một cái gì đó như cdl(liên kết cd), nó sẽ đưa tôi đến thư mục của tệp được liên kết (hoặc thay vào đó là thư mục được liên kết, nếu đó là trường hợp nếu đó là tôi có thể gõ cd -P /bar).


Tôi có thể hỏi động lực của bạn là gì để làm điều này? Ngoài ra, bạn có muốn giải quyết đệ quy symlink không? (Nếu / thanh tự nó là một liên kết tượng trưng, ​​bạn có muốn theo dõi nó không?)
200_success

Câu trả lời:


7

Trong zsh, có một công cụ sửa đổi cho điều đó, hay đúng hơn là hai: Ađể giải quyết các liên kết tượng trưng (với realpath ) và hđể trích xuất phần đầu não (tức là dirname).

cd $file(:A:h)

Điều này chỉ hoạt động nếu biểu tượng không bị hỏng. Nếu có một chuỗi các liên kết tượng trưng, ​​nó được theo dõi cho đến khi mục tiêu cuối cùng. Nếu thư mục được truy cập thông qua một liên kết tượng trưng, ​​bạn sẽ ở trong mục tiêu của nó (như với cd -P).


Nếu không có zsh, nếu bạn có readlinktiện ích và bạn muốn thay đổi thư mục chứa mục tiêu của liên kết tượng trưng:

cd -- "$(dirname -- "$(readlink -- "$file")")"

Mục tiêu của liên kết có thể là một liên kết tượng trưng. Nếu bạn muốn thay đổi thư mục chứa mục tiêu cuối cùng của liên kết, bạn có thể gọi readlinktrong một vòng lặp:

while [ -L "$file" ]; do
  target=$(readlink -- "$file")
  while case $target in */) target=${target%/};; *) false;; esac; done
  case $target in
    */*) cd -- "${target%/*}"; target=${target#**/};;
  esac
done

Trên Linux, giả sử symlink không bị hỏng, bạn có thể sử dụng readlink -fđể chuẩn hóa đường dẫn:

t=$(readlink -f -- "$file")
cd "${t%/*}"

Câu trả lời tuyệt vời: cd $file(:A:h)chính xác là những gì tôi đang tìm kiếm!
Chauncey Garrett

7

Bạn có thể sử dụng readlinkđể giải quyết liên kết tượng trưng và sau đó dirnameđể có được thư mục của nó.

cdl () {
    cd "$(dirname "$(readlink "$1")")"; 
}
bash-3.2$ pwd
/foo/bar
bash-3.2$ ls -l
total 8
lrwxr-xr-x  1 root  wheel  11 Jun 15 19:10 foo.sh -> /bar/foo.sh
bash-3.2$ cdl foo.sh 
bash-3.2$ pwd 
/bar
bash-3.2$ 

1
NB đây là một ví dụ hoàn hảo về lý do tại sao nên sử dụng $()thay vì backticks.
Kevin

0

một đường thẳng:

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

Đây là câu trả lời một dòng thứ hai của bạn (thậm chí nó có vẻ giống hệt câu trả lời). Một lần nữa, câu trả lời một dòng không phải là hữu ích nhất. Vui lòng mở rộng câu trả lời của bạn để bao gồm thông tin và giải thích hữu ích hơn (bao gồm các liên kết và tài liệu hỗ trợ).
HalosGhost
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.