Tại sao tập lệnh Bash của tôi không nhận ra bí danh?


216

Trong ~/.bashrctập tin của tôi có hai định nghĩa:

  1. commandA, đó là bí danh cho một con đường dài hơn
  2. commandB, đó là bí danh của tập lệnh Bash

Tôi muốn xử lý cùng một tệp với hai lệnh này, vì vậy tôi đã viết tập lệnh Bash sau:


#!/bin/bash

for file in "$@"
    do
    commandA $file
    commandB $file
done

Ngay cả sau khi đăng xuất khỏi phiên của tôi và đăng nhập lại, Bash vẫn nhắc tôi về các command not foundlỗi cho cả hai lệnh khi tôi chạy tập lệnh này.

Tôi đang làm gì sai?


10
BTW, không cần phải đăng nhập và đăng xuất để có bí danh được công nhận. Bạn chỉ cần làm source ~/.bashrc.
tshepang

Đối với trường hợp của tôi, tôi đã được kết nối bởi tác nhân SSH từ xa, sau khi thêm bí danh khi tôi đóng tác nhân SSH và kết nối lại, nó bắt đầu hoạt động.
dav

Bí danh là một cách rút ngắn một lệnh. (Chúng chỉ được sử dụng trong các vỏ tương tác chứ không phải trong các tập lệnh - đây là một trong số rất ít sự khác biệt giữa tập lệnh và trình bao tương tác.)
Kris Roofe

Câu trả lời:


117

Trước hết, như ddeimeke đã nói, các bí danh theo mặc định không được mở rộng trong các vỏ không tương tác.

Thứ hai, .bashrckhông được đọc bởi các shell không tương tác trừ khi bạn đặt BASH_ENVbiến môi trường.

Nhưng quan trọng nhất: đừng làm vậy! Xin vui lòng? Một ngày nào đó bạn sẽ di chuyển tập lệnh đó đến một nơi mà các bí danh cần thiết không được đặt và nó sẽ bị hỏng lần nữa.

Thay vào đó, hãy đặt và sử dụng các biến môi trường làm các phím tắt trong tập lệnh của bạn:

#!/bin/bash

CMDA=/path/to/gizmo
CMDB=/path/to/huzzah.sh

for file in "$@"
do
    $CMDA "$file"
    $CMDB "$file"
done

5
Giải pháp đó không hoạt động cho các aliastrường hợp sử dụng thông thường . Ví dụ alias mv="mv -v --backup=numbered".
Evi1M4chine

@ Evi1M4chine: Vâng, đúng vậy. Ít nhất là sau khi tôi hoàn nguyên Gilles chỉnh sửa không cần thiết. Nhưng dù sao thì cũng nên sử dụng một biến khác cho các tham số.

1
Ah, lưu ý các thiếu của dấu ngoặc kép quanh $CMDA/ $CMDB... Ngoài các biến chữ hoa được dành cho bash chính nó trong bash, và nó thực sự làm việc, mà thiếu dấu ngoặc kép khiến tôi thực sự lo lắng ... Thanks anyway.
Evi1M4chine

@ Evi1M4chine: Uh, cái gì? 1. Tôi đã tự xóa các trích dẫn trong lần chỉnh sửa gần đây nhất. 2. bạn lấy "dành riêng cho bash" từ đâu? đây sẽ là lần đầu tiên tôi nghe về nó 3. Nếu điều đó làm bạn khó chịu, bạn cảm thấy thế nào khi sử dụng bash ngay từ đầu? Dù sao, sử dụng một biến riêng cho các tùy chọn như tôi đã nói với bạn.

1
@alvas: giả định là gizmokhông nằm trên đường dẫn hoặc có một lệnh có cùng tên nhưng có mức độ ưu tiên cao hơn. nếu không bạn có thể đơn giản thiết lập CMDAđể đồng bằng gizmoở nơi đầu tiên.

161

Nếu bạn nhìn vào trang bash bạn tìm thấy:

Các bí danh không được mở rộng khi shell không tương tác, trừ khi tùy chọn shell extend_aliases được đặt bằng shopt (xem mô tả về shopt trong SHELL BUILTIN THÔNG TIN bên dưới).

Vì vậy, đặt một

shopt -s expand_aliases

trong kịch bản của bạn.

Đảm bảo nguồn tệp bí danh của bạn sau khi đặt tệp này trong tập lệnh của bạn.

shopt -s expand_aliases
source ~/.bash_aliases

7
Tôi đã đặt nó trong kịch bản của mình, nhưng nó vẫn không hoạt động. Cùng một lỗi.
Zaid

5
Thêm shopt -s expand_aliases source ~/.bash_aliasescông việc hoàn hảo cho tôi. Thường có một hình thức phát hiện shell tương tác trong .bashrc như thế này: # If not running interactively, don't do anything [ -z "$PS1" ] && return@Zaid, Có thể bạn muốn kiểm tra xem trong tệp bạn có nguồn gốc.
Frank Schubert

1
Xuất sắc! đã lưu tập lệnh của tôi !! :) thật khó để đọc / tìm kiếm / duyệt thông tin và các trang trong thiết bị đầu cuối mà tôi đã từ bỏ từ lâu và tìm kiếm trên internet ...
Aquarius Power

2
Thật kỳ lạ, shopt -s expand_aliaseskhông phải đi trước định nghĩa bí danh mà trước khi sử dụng bí danh. Thêm vào @FrankSchubert: Phát hiện hệ vỏ tương tác cũng có thể được thực hiện bằng cách sử dụng $-có chứa các tùy chọn cho trình bao, đặc biệt inếu trình bao tương tác.
hợp lệ

2
đây không phải là một câu trả lời đúng ... Tìm nguồn bí danh của bạn trong tập lệnh của bạn không phải là câu trả lời. Bạn ~/.bash_aliasescó thể phụ thuộc vào những thứ khác được tải trước đó trên vỏ tương tác ... Điều gần nhất tôi tìm thấy là thay đổi hashbang của bạn thành #!/bin/bash -liVẫn không hoàn hảo. Tốt nhất bạn nên sử dụng các hàm và không phải bí danh.
Stefanos Kalantzis

44

Các bí danh không thể được xuất để chúng không có sẵn trong các tập lệnh shell mà chúng không được xác định. Nói cách khác, nếu bạn xác định chúng trong ~/.bashrcchúng không có sẵn your_script.sh(trừ khi bạn lấy nguồn ~/.bashrctrong tập lệnh, điều mà tôi không khuyến nghị nhưng có nhiều cách để làm điều này đúng).

Tuy nhiên, các hàm có thể được xuất và sẽ có sẵn cho các tập lệnh shell được chạy từ một môi trường mà chúng được xác định. Điều này có thể được thực hiện bằng cách đặt cái này trong bashrc của bạn:

foo ()
{
    tiếng vang "Xin chào thế giới!"
}
xuất-foo

Như hướng dẫn của Bash nói, "Đối với hầu hết mọi mục đích, các hàm shell được ưa thích hơn các bí danh."


1
Mặc dù điều này không trả lời về mặt kỹ thuật câu hỏi, như bạn nói, bạn chỉ có thể thay thế alias commandA=...bằng cách commandA() { ... }đó export commandAvà bạn có hành vi giống hệt với bí danh. Vì vậy, đây là khá nhiều thay thế giống hệt với bí danh theo như tôi biết rằng nó hoạt động rất tốt trong các tập lệnh bash
Phylliida

Vấn đề ở đây là khi bạn cần một bí danh mà bạn vượt qua rất nhiều tùy chọn được trích dẫn. ví dụ như một ví dụ, alias b=bashlàm cho nó dễ thực hiện b -c "echo test | grep test"mà khó thực hiện trong các hàm.
Fmstrat

@Fmstrat: b () { bash "$@"; }sau đób -c "echo test | grep test"
Dennis Williamson

11
[cmd line] > bash -i [your script's file path]

Đây ilà để tương tác và nguồn bashhồ sơ của bạn cho bạn.


-5

Đôi khi tôi cũng thấy bash script không nhận ra xuất. Tuy nhiên, thay đổi nó thành

#!/bin/sh

làm việc cho tôi


1
Không, nó không ...
Hafiz Temuri
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.