Bí danh cho CD trong một thư mục và gọi lệnh


21

Tôi có một .bash_profilevà trong đó tôi có một bộ bí danh. Những bí danh tại thời điểm này chỉ thực hiện một lệnh duy nhất và nó khá dễ dàng. Tuy nhiên tôi muốn làm hai điều với một bí danh mới mà tôi đang cố gắng tạo ra.

  1. CD vào một thư mục
  2. Chạy một lệnh từ thư mục đó

Câu trả lời:


26

Để thực thi một lệnh với một thư mục làm việc cụ thể, người ta thường làm

( cd directory && utility )

Các dấu ngoặc đơn xung quanh cd ...có nghĩa là (các) lệnh trong đó chạy trong một khung con. Việc thay đổi thư mục làm việc trong một lớp con làm cho nó để thư mục làm việc hiện tại của vỏ gọi không bị thay đổi, tức là, sau khi đã gọi lệnh này, bạn vẫn sẽ nằm trong cùng thư mục nơi bạn bắt đầu.

Thí dụ:

( cd / && echo "$PWD" )  # will output "/"
echo "$PWD"              # will output whatever directory you were in at the start

Điều này không thể được biến thành bí danh chung vì bí danh không thể lấy bất kỳ đối số nào.

Đối với một thư mục cụ thể và tiện ích, người ta có thể làm

alias cdrun='( cd "$HOME/somedir" && ./script.sh )'

nhưng đối với trường hợp chung, bạn sẽ phải sử dụng hàm shell:

cdrun () {
    ( cd "$1" && shift && command "$@" )
}

hoặc là

cdrun () (
    cd "$1" && shift && command "$@"
)

Việc thay thế các dấu ngoặc nhọn bằng dấu ngoặc đơn quanh thân hàm làm cho hàm thực thi trong lớp con của chính nó.

Điều này sẽ được sử dụng như

$ cdrun "$HOME/somedir" ./script.sh

mà sẽ chạy tập lệnh script.shnằm trong thư mục $HOME/somedir, với $HOME/somedirtư cách là thư mục làm việc, hoặc

$ cdrun / ls -l

sẽ cung cấp cho bạn một danh sách thư mục theo "định dạng dài" của thư mục gốc.

Hàm shell lấy đối số đầu tiên của nó và cố gắng thay đổi thư mục đó. Nếu nó hoạt động, nó sẽ tắt tên thư mục khỏi các tham số vị trí (danh sách đối số dòng lệnh) và thực thi lệnh được đưa ra bởi phần còn lại của các đối số. commandlà một lệnh tích hợp trong shell, nó chỉ đơn giản thực hiện các đối số của nó như là một lệnh.


Tất cả điều này là cần thiết nếu bạn muốn thực thi một lệnh với một thư mục làm việc đã thay đổi . Nếu bạn chỉ muốn thực thi một lệnh nằm ở nơi khác, rõ ràng bạn có thể sử dụng

alias thing='$HOME/somedir/script.sh'

nhưng điều này sẽ chạy script.shnằm ở $HOME/somedirvới hiện tại thư mục như thư mục làm việc.

Một cách khác để thực thi một tập lệnh nằm ở nơi khác mà không thay đổi thư mục làm việc là thêm vị trí của tập lệnh vào PATHbiến môi trường của bạn , ví dụ:

PATH="$PATH:$HOME/somedir"

Bây giờ script.shtrong $HOME/somedirsẽ có thể được chạy từ bất cứ nơi nào bằng cách chỉ sử dụng

$ script.sh

Một lần nữa, điều này không thay đổi thư mục làm việc cho lệnh.


2
Câu trả lời xuất sắc, toàn diện. Tôi chỉ nghĩ rằng tôi muốn đề cập rằng định nghĩa hàm chỉ cần một phương thức nhóm các lệnh và dấu ngoặc đơn cho lớp con là đủ : cdrun () ( cd "$1" && shift && command "$@" ).
Anthony G - công lý cho Monica

2
@AnthonyGeoghegan Ah, đó là sự thật. Tôi luôn luôn sử dụng { ... }cho sự nhất quán với các chức năng dài hơn mặc dù.
Kusalananda

Câu hỏi và trả lời này dường như nói lên tình huống của tôi và có thể là một sự cải thiện trong việc sử dụng xung quanh pushdpopd( > /dev/nullnếu bạn cũng đang cố gắng tránh các thông điệp đầu ra), trong khi vẫn giữ cho bối cảnh sạch sẽ!
Pysis

1
@Pysis Có, (cd dir && thing)cũng dễ mang theo hơn nhiều so với sử dụng pushdpopd.
Kusalananda

@Kusalananda Thật sao? Tôi đã có họ làm việc cho ít nhất một số hệ thống.
Pysis

4
alias <name-of-the-alias>='cd <the-directory> && <command>'

Vì vậy, nếu bạn muốn thay đổi thư mục (cd) thành thư mục /var/log/và sau đó liệt kê (ls) các tệp của nó, bạn có thể nối vào .bash_profiletệp của mình như sau:

alias logs='cd /var/log/ && ls'

1

Tôi sử dụng chức năng này để chạy một lệnh trong một thư mục khác:

cd1 () {
  if [ $# -eq 1 ]; then
    command cd -- "$1"
  else
    ( command cd -- "$1" && shift && "$@" )
  fi
}

Một hạn chế của chức năng này là các ký tự đại diện được hoàn thành so với thư mục gốc, không liên quan đến thư mục nơi lệnh chạy. Có thể làm tốt hơn trong zsh .

Hàm này hoạt động như bình thường cdnếu được gọi với một đối số duy nhất, vì vậy bạn có thể muốn gọi nó cd. (Chức năng này không hỗ trợ bất kỳ tùy chọn nào, nhưng các tùy chọn cdhiếm khi được sử dụng.)


-1

Các lệnh riêng biệt bằng dấu chấm phẩy, ví dụ:

alias do_something='cd /tmp; ls'

8
Nếu cdthất bại, bạn sẽ nhận được danh sách thư mục của thư mục sai. Tốt hơn là sử dụng &&thay vì ;ở đây.
Kusalananda

@Kusalananda nói đúng. Bạn có thể tìm thấy nhiều hơn trong câu trả lời
nikolas
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.