Trong Bash, khi nào bí danh, khi nào kịch bản và khi nào viết một hàm?


360

Tôi đã mất gần 10 năm sử dụng Linux để đặt câu hỏi này. Đó là tất cả các thử nghiệm và lỗi và lướt web đêm khuya ngẫu nhiên.

Nhưng mọi người không cần 10 năm cho việc này. Nếu tôi chỉ mới bắt đầu với Linux, tôi muốn biết: Khi nào bí danh, khi nào kịch bản và khi nào viết một chức năng?

Trường hợp bí danh có liên quan, tôi sử dụng bí danh cho các hoạt động rất đơn giản mà không tranh luận.

alias houston='cd /home/username/.scripts/'

Điều đó có vẻ hiển nhiên. Nhưng một số người làm điều này:

alias command="bash bashscriptname"

(và thêm nó vào .bashrctập tin)

Có một lý do tốt để làm điều đó? Tôi đang rất cố gắng, nhưng tôi thực sự không thể nghĩ ra bất kỳ hoàn cảnh nào mà tôi muốn làm điều đó. Vì vậy, nếu có một trường hợp cạnh mà sẽ làm cho một sự khác biệt, xin vui lòng trả lời dưới đây.

Bởi vì đó là nơi tôi sẽ đặt một cái gì đó vào PATH của tôi và chmod +xnó, đó là một thứ khác xuất hiện sau nhiều năm thử và sửa lỗi Linux.

Điều này đưa tôi đến chủ đề tiếp theo. Chẳng hạn, tôi đã thêm một thư mục ẩn ( .scripts/) trong thư mục chính vào PATH của mình bằng cách thêm một dòng vào .bashrc( PATH=$PATH:/home/username/.scripts/) của tôi , vì vậy mọi thứ có thể thực thi trong đó tự động hoàn thành.

Nếu tôi cần.

Tôi thực sự không cần điều đó, phải không? Tôi sẽ chỉ sử dụng nó cho các ngôn ngữ không phải là shell, như Python.

Nếu đó là shell, tôi chỉ có thể viết một hàm bên trong giống nhau .bashrc:

funcname () {
  somecommand -someARGS "$@"
}

Như tôi đã nói, tôi đã tìm thấy rất nhiều điều này thông qua thử nghiệm và lỗi. Và tôi chỉ thực sự thấy vẻ đẹp của các chức năng khi máy tính của tôi chết và tôi buộc phải sử dụng máy tính của những người xung quanh khi họ không sử dụng chúng.

Thay vì chuyển toàn bộ thư mục các tập lệnh từ máy tính sang máy tính, cuối cùng tôi chỉ thay thế .bashrc của người khác bằng chính tôi, vì họ thậm chí chưa bao giờ thực hiện một sửa đổi nào.

Nhưng tôi có bỏ lỡ điều gì không?

Vậy, bạn sẽ nói gì với người dùng Linux mới bắt đầu về khi nào bí danh, khi nào tập lệnh và khi nào viết một hàm?

Nếu nó không rõ ràng, tôi cho rằng những người trả lời điều này sẽ sử dụng cả ba tùy chọn. Nếu bạn chỉ sử dụng bí danh, hoặc chỉ sử dụng các tập lệnh, hoặc chỉ sử dụng các chức năng , hoặc nếu bạn chỉ sử dụng các bí danh và tập lệnh hoặc bí danh và các chức năng hoặc tập lệnh và chức năng thì câu hỏi của Wapthis không thực sự nhắm vào bạn.


5
có thể trùng lặp các hàm bash so với tập lệnh
Gilles

10
+1 cho việc nêu rõ tất cả các tập hợp con của {bí danh, tập lệnh, hàm} mà câu hỏi này không nhắm tới. +1 cho niềm tin như trẻ con rằng bạn có thể bỏ qua tập hợp con null.
Thomas L Holaday

1
Mặc dù câu hỏi được hỏi cụ thể về bash, lưu ý rằng các vỏ Bourne cũ hơn có 'bí danh' nhưng không có chức năng. Điều này có thể tạo sự khác biệt nếu bạn lo lắng về khả năng tương thích.
AndyB

Nếu .bashrc thực sự là nơi tốt nhất, hoặc ít nhất là một nơi vững chắc, cho điều này? Có rất nhiều cách để làm điều tương tự trong Linux, điều mà tôi đánh giá cao, tuy nhiên, tất cả mọi thứ đều bình đẳng, tôi thích làm mọi thứ theo cách phổ biến nhất.
Kit10

Câu trả lời:


242

Một bí danh thực sự không nên (nói chung) làm nhiều hơn thay đổi các tùy chọn mặc định của lệnh. Nó không có gì khác hơn là thay thế văn bản đơn giản trên tên lệnh. Nó không thể làm bất cứ điều gì với các đối số nhưng chuyển chúng đến lệnh mà nó thực sự chạy. Vì vậy, nếu bạn chỉ cần thêm một đối số ở phía trước của một lệnh, một bí danh sẽ hoạt động. Ví dụ phổ biến là

# Make ls output in color by default.
alias ls="ls --color=auto"
# make mv ask before overwriting a file by default
alias mv="mv -i"

Một hàm nên được sử dụng khi bạn cần làm một cái gì đó phức tạp hơn bí danh nhưng nó sẽ không được sử dụng riêng. Ví dụ: lấy câu trả lời này cho câu hỏi tôi đã hỏi về việc thay đổi grephành vi mặc định tùy thuộc vào việc nó có trong đường ống hay không:

grep() { 
    if [[ -t 1 ]]; then 
        command grep -n "$@"
    else 
        command grep "$@"
    fi
}

Đây là một ví dụ hoàn hảo về chức năng vì nó quá phức tạp đối với bí danh (yêu cầu các giá trị mặc định khác nhau dựa trên một điều kiện), nhưng đó không phải là thứ bạn cần trong một kịch bản không tương tác.

Nếu bạn nhận được quá nhiều chức năng hoặc chức năng quá lớn, hãy đặt chúng vào các tệp riêng biệt trong một thư mục ẩn và nhập chúng vào ~/.bashrc:

if [ -d ~/.bash_functions ]; then
    for file in ~/.bash_functions/*; do
        . "$file"
    done
fi

Một kịch bản nên tự đứng. Nó nên có giá trị như một cái gì đó có thể được sử dụng lại, hoặc được sử dụng cho nhiều mục đích.


14
Điều quan trọng cần nhớ là - trừ khi có nguồn gốc .hoặc source- một tập lệnh được thực thi bằng quy trình bash riêng và có môi trường riêng. Vì lý do này, bất cứ điều gì sửa đổi môi trường shell (ví dụ: hàm, biến, v.v.) sẽ không tồn tại trong môi trường shell mà bạn chạy tập lệnh.
Will Vousden

260

Các câu trả lời khác cung cấp một số hướng dẫn chung mềm dựa trên sở thích cá nhân, nhưng bỏ qua nhiều sự thật thích hợp mà người ta nên xem xét khi quyết định giữa các tập lệnh, chức năng hoặc bí danh.

Bí danh và Chức năng

  • Toàn bộ nội dung của bí danh và chức năng được lưu trữ trong bộ nhớ của shell.
  • Một kết quả tự nhiên của điều này là các bí danh và các hàm chỉ có thể được sử dụng bởi trình bao hiện tại, chứ không phải bởi bất kỳ chương trình nào khác mà bạn có thể gọi từ trình bao như trình soạn thảo văn bản, tập lệnh hoặc thậm chí các phiên bản con của cùng trình bao.
  • Các bí danh và hàm được thực thi bởi shell hiện tại, tức là chúng chạy bên trong và ảnh hưởng đến môi trường hiện tại của shell.² Không có quy trình riêng biệt nào là cần thiết để chạy bí danh hoặc hàm.

Chữ viết

  • Shell không giữ tập lệnh trong bộ nhớ. Thay vào đó, các tập lệnh được đọc từ các tệp nơi chúng được lưu trữ mỗi khi chúng cần thiết. Nếu tập lệnh được tìm thấy thông qua $PATHtìm kiếm, nhiều shell lưu trữ một hàm băm tên đường dẫn của nó trong bộ nhớ để tiết kiệm thời gian cho các $PATHtra cứu trong tương lai , nhưng đó là phạm vi của dấu chân bộ nhớ của tập lệnh khi không sử dụng.
  • Các kịch bản có thể được gọi theo nhiều cách hơn các hàm và bí danh có thể. Chúng có thể được truyền dưới dạng đối số cho trình thông dịch, như sh script, hoặc được gọi trực tiếp dưới dạng thực thi, trong trường hợp đó, trình thông dịch trong dòng shebang (ví dụ #!/bin/sh) được gọi để chạy nó. Trong cả hai trường hợp, tập lệnh được điều hành bởi một quy trình thông dịch riêng với môi trường riêng tách biệt với môi trường của trình bao của bạn, tập lệnh mà kịch bản không thể ảnh hưởng theo bất kỳ cách nào. Thật vậy, trình bao thông dịch thậm chí không phải khớp với trình gọi. Bởi vì các tập lệnh được gọi theo cách này dường như hoạt động giống như bất kỳ chương trình thực thi thông thường nào, chúng có thể được sử dụng bởi bất kỳ chương trình nào.

    Cuối cùng, một tập lệnh có thể được đọc và chạy bởi shell hiện tại với .hoặc trong một số shell , source. Trong trường hợp này, tập lệnh hoạt động giống như một chức năng được đọc theo yêu cầu thay vì liên tục được giữ trong bộ nhớ.

Ứng dụng

Với những điều trên, chúng ta có thể đưa ra một số hướng dẫn chung về việc có nên tạo một cái gì đó thành tập lệnh hay hàm / bí danh hay không.

  • Các chương trình khác ngoài vỏ của bạn cần có thể sử dụng nó? Nếu vậy, nó phải là một kịch bản.

  • Bạn chỉ muốn nó có sẵn từ một vỏ tương tác? Điều thông thường là muốn thay đổi hành vi mặc định của nhiều lệnh khi chạy tương tác mà không ảnh hưởng đến các lệnh / tập lệnh bên ngoài. Trong trường hợp này, hãy sử dụng một bí danh / hàm được đặt trong tệp RC "chỉ chế độ tương tác" của shell (đối với bashđiều này là .bashrc).

  • Có cần thay đổi môi trường của vỏ không? Cả hàm / bí danh hoặc tập lệnh có nguồn gốc đều là những lựa chọn có thể.

  • Nó có phải là thứ bạn sử dụng thường xuyên không? Có thể hiệu quả hơn để giữ nó trong bộ nhớ, vì vậy hãy biến nó thành một hàm / bí danh nếu có thể.

  • Ngược lại, nó chỉ là thứ bạn sử dụng hiếm khi? Trong trường hợp đó, sẽ không có cảm giác có bộ nhớ hog khi bạn không cần nó, vì vậy hãy biến nó thành một kịch bản.


Trong khi các hàm và bí danh có một số khác biệt quan trọng, chúng được nhóm lại với nhau vì các hàm có thể làm mọi thứ bí danh có thể. Các bí danh không thể có các biến cục bộ cũng như không thể xử lý các đối số và chúng bất tiện cho bất cứ điều gì dài hơn một dòng.

² Mọi quy trình đang chạy trong hệ thống Unix đều có một môi trường bao gồm một loạt các variable=valuecặp thường chứa các cài đặt cấu hình toàn cầu, như LANGngôn ngữ mặc định và PATHđể chỉ định đường dẫn tìm kiếm thực thi.


26
IMHO Đây là câu trả lời tốt nhất.
Luc M

4
Các định dạng câu hỏi / câu trả lời là một ý tưởng tuyệt vời. Tôi có thể đánh cắp điều đó. ;-)
Mikel

4
Đáng lưu ý: nếu hai (hoặc nhiều) tập lệnh cần chia sẻ một số mã, có lẽ tốt nhất là đặt mã đó vào một hàm nằm trong tệp thứ ba mà cả hai tập lệnh đó nhập / nguồn.
kbolino

3
Một mục khác để thêm vào danh sách câu hỏi đó: Bạn có bao giờ cần thay đổi chức năng trong lệnh khi đang di chuyển không? các thay đổi đối với tập lệnh sẽ được phản ánh trong tất cả các phiên, trong khi các chức năng và bí danh phải được tải lại hoặc xác định lại trên cơ sở mỗi phiên.
Stratus3D

3
Câu trả lời tốt. Một điều quan trọng hơn (đối với tôi): khi tạo "lối tắt" cho các tiện ích khác, tốt hơn là sử dụng bí danh vì tự động hoàn thành hiện tại sẽ chỉ hoạt động với các bí danh, nhưng không phải với các tập lệnh hoặc hàm (vì vậy +1 cho các bí danh). ví dụ: Bằng cách tạo alias g='gradle'tự động hoàn thành cấp độ khi tôi sử dụng gbí danh của mình , nhưng sẽ không nhận được nó ngay lập tức khi sử dụng tập lệnh có gradle $*hoặc một chức năng vớigradle $@
Yoav Aharoni

37

Tôi nghĩ rằng nó tùy thuộc vào khẩu vị của mỗi người. Đối với tôi logic đi như thế này:

  • Đầu tiên tôi cố gắng tạo bí danh, vì đó là cách đơn giản nhất.
  • Nếu điều này quá phức tạp để phù hợp với một dòng, tôi cố gắng làm cho nó trở thành một chức năng.
  • Khi hàm bắt đầu phát triển vượt quá hàng chục dòng, tôi đặt nó vào một tập lệnh.

Thực sự không có gì để hạn chế bạn làm điều gì đó hoạt động .


6
Tôi thường bỏ qua tùy chọn chức năng, và tạo một kịch bản ngay lập tức. Nhưng tôi đồng ý rằng đó là một phần của vấn đề hương vị
Bernhard

2
Một hàm bắt đầu có ý nghĩa nếu bạn cần nó trong một số tập lệnh.
Nils

7
... Hoặc nếu bạn cần các tác dụng phụ để thay đổi lớp vỏ hiện tại .
glenn jackman

có ý nghĩa, người đàn ông!
nhà thám hiểm

15

Ít nhất một phần đó là vấn đề sở thích cá nhân. Mặt khác, có một số khác biệt về chức năng rõ ràng:

  • bí danh: chỉ thích hợp cho việc thay thế văn bản đơn giản, không có đối số / tham số
  • các chức năng: dễ viết / sử dụng, khả năng kịch bản shell đầy đủ, chỉ có sẵn trong bash
  • tập lệnh: ít nhiều giống như các hàm, nhưng cũng có sẵn (có thể gọi được) bên ngoài bash

Nhìn vào kịch bản shell tôi đã thực hiện trong vài năm qua, tôi đã ít nhiều ngừng viết bí danh (bởi vì tất cả chúng đều có xu hướng phát triển thành các chức năng theo thời gian) và chỉ thực hiện các kịch bản nếu chúng cần có sẵn từ các môi trường không có bash.

Tái bút: alias command="bash bashscriptname"Tôi thực sự không thấy bất kỳ lý do nào để làm điều này. Ngay cả khi bashscriptnamekhông có trong $ PATH, một đơn giản alias c=/path/to/scriptsẽ là đủ.


1
Trong alias command="bash bashscriptname"kịch bản không nhất thiết phải được thực thi; trong alias c=/path/to/scriptnó phải
Martin - ー チ

Điều đó không đúng với tất cả các chức năng "chỉ có sẵn bên trong Bash". Nếu bạn muốn nói rằng chúng là một tính năng chỉ dành cho Bash, thì điều đó đơn giản là sai (shell Bourne và mọi dẫn xuất tương thích đều có chúng); và nếu bạn muốn nói rằng chúng là một tính năng của shell tương tác, thì điều đó cũng không chính xác (mặc dù bí danh, biến và hàm được xác định trong tệp được tải khi khởi động bởi shell tương tác rõ ràng sẽ không được tải bởi shell không tương tác).
tripleee

@tripleee Ý nghĩa giống như "bạn không thể exec()bao hàm các hàm" :-)
nohillside

11

Dưới đây là một số điểm bổ sung về bí danh và chức năng:

  • Bí danh và chức năng cùng tên có thể cùng tồn tại
  • không gian tên bí danh được tra cứu đầu tiên (xem ví dụ đầu tiên)
  • bí danh không thể (un) được đặt trong môi trường con hoặc môi trường không tương tác (xem ví dụ thứ hai)

Ví dụ:

alias f='echo Alias'; f             # prints "Alias"
function f { echo 'Function'; }; f  # prints "Alias"
unalias f; f                        # prints "Function"

Như chúng ta có thể thấy, có các không gian tên riêng cho các bí danh và hàm; nhiều chi tiết có thể được tìm thấy bằng cách sử dụng declare -A -p BASH_ALIASESdeclare -f fin ra định nghĩa của chúng (cả hai đều được lưu trong bộ nhớ).

Ví dụ cho thấy các hạn chế của bí danh:

alias a='echo Alias'
a        # OK: prints "Alias"
eval a;  # OK: prints "Alias"
( alias a="Nested"; a );  # prints "Alias" (not "Nested")
( unalias a; a );         # prints "Alias"
bash -c "alias aa='Another Alias'; aa"  # ERROR: bash: aa: command not found

Như chúng ta có thể thấy bí danh không thể lồng nhau, không giống như các hàm. Ngoài ra, việc sử dụng của họ được giới hạn trong các phiên tương tác.

Cuối cùng, lưu ý rằng bạn có thể tính toán tùy ý trong một bí danh bằng cách khai báo một hàm ngay lập tức gọi nó, như vậy:

alias a_complex_thing='f() { do_stuff_in_function; } f'

đã được sử dụng rộng rãi trong trường hợp bí danh Git. Lợi ích của việc khai báo hàm là bí danh của bạn có thể được ghi đè đơn giản bằng cách nhập nguồn (hoặc sử dụng .) một tập lệnh xảy ra để khai báo hàm cùng tên.


10

Khi nào nên viết kịch bản ...

  • Các kịch bản tập hợp các thành phần phần mềm (còn gọi là các công cụ, lệnh, quy trình, thực thi, chương trình) thành các thành phần phức tạp hơn, có thể tự chúng được lắp ráp thành các thành phần phức tạp hơn.
  • Các kịch bản thường được thực hiện để chúng có thể được gọi bằng tên. Khi được gọi, một quy trình con mới được sinh ra để tập lệnh chạy vào. Bản sao của bất kỳ exportbiến ed và / hoặc hàm nào được truyền theo giá trị cho tập lệnh. Thay đổi đối với các biến đó không truyền trở lại tập lệnh cha.
  • Các tập lệnh cũng có thể được tải (có nguồn gốc) như thể chúng là một phần của tập lệnh gọi. Điều này tương tự với những gì một số ngôn ngữ khác gọi là "nhập khẩu" hoặc "bao gồm". Khi có nguồn gốc, họ thực hiện trong quy trình hiện có. Không có quy trình con được sinh ra.

Khi nào nên viết một hàm ...

  • Các chức năng là các kịch bản shell được tải sẵn hiệu quả. Họ thực hiện tốt hơn một chút so với việc gọi một tập lệnh riêng biệt, nhưng chỉ khi nó phải được đọc từ đĩa cơ. Ngày nay, sự phát triển của flashdrive, SSD và bộ nhớ cache thông thường của Linux trong RAM không sử dụng làm cho sự cải thiện đó không thể đo lường được.
  • Các chức năng đóng vai trò là nguyên tắc của bash có nghĩa là đạt được tính mô đun, đóng gói và tái sử dụng. Họ cải thiện sự rõ ràng, độ tin cậy và khả năng duy trì của các kịch bản.
  • Các quy tắc cú pháp để gọi một hàm giống hệt như gọi một hàm thực thi. Một hàm có cùng tên với một tệp thực thi sẽ được gọi thay vì thực thi.
  • Các chức năng là cục bộ của tập lệnh mà chúng đang ở.
  • Các hàm có thể được xuất ( sao chép theo giá trị ) để chúng có thể được sử dụng bên trong các tập lệnh được gọi. Vì vậy, các chức năng chỉ truyền đến các quá trình con, không bao giờ cha mẹ.
  • Các hàm tạo các lệnh có thể tái sử dụng thường được tập hợp thành các thư viện (một tập lệnh chỉ có các định nghĩa hàm) được lấy từ các tập lệnh khác.

Khi nào nên viết bí danh ...

Trong các tập lệnh như tập lệnh thư viện, đôi khi cần một bí danh cho một chức năng, chẳng hạn như khi một chức năng được đổi tên nhưng cần có khả năng tương thích ngược. Điều này có thể được thực hiện bằng cách tạo một hàm đơn giản với tên cũ chuyển tất cả các đối số của nó sang hàm mới ...

# A bash in-script 'alias'
function oldFunction () { newFunction "$@"; }

9

Một điều khác mà tôi không tin đã được đưa ra: một hàm thực thi trong bối cảnh của quá trình gọi, trong khi một kịch bản tạo ra một lớp vỏ mới.

Điều này có thể quan trọng đối với hiệu suất - một chức năng nhanh hơn, vì nó không fork()exec(). Trong trường hợp bình thường, sự khác biệt là không đáng kể, nhưng nếu bạn gỡ lỗi một hệ thống hết bộ nhớ và bị lỗi trang, nó có thể tạo ra sự khác biệt lớn.

Ngoài ra, nếu bạn muốn sửa đổi môi trường shell hiện tại của mình, bạn nên sử dụng một hàm. Ví dụ, một hàm có thể thay đổi tra cứu lệnh $PATHcho shell hiện tại, nhưng tập lệnh không thể, bởi vì nó hoạt động trên bản sao fork / exec của $PATH.


Làm thế nào để tuyên truyền các chức năng cho trẻ em làm việc?
HappyFace

1
@HappyFace Trong Bash bạn có thể thực hiện export -fmột chức năng, mặc dù các hoạt động bên trong chính xác của điều này có phần mơ hồ. Tôi tin rằng đây không phải là di động cho vỏ Bourne truyền thống.
tripleee

7

Script và bí danh và script và chức năng không loại trừ lẫn nhau. Bạn có thể và lưu trữ các bí danh và chức năng trong các tập lệnh.

Các kịch bản chỉ là mã được thực hiện liên tục . Các hàm và bí danh hữu ích mà bạn muốn sử dụng trong tương lai được lưu trữ trong các tập lệnh. Tuy nhiên, một tập lệnh thường là một tập hợp của nhiều hơn một chức năng.

Vì các bí danh không được tham số hóa , chúng rất hạn chế; thường để xác định một số tham số mặc định.

Một chức năng là một đơn vị riêng biệt của mã , một khái niệm rõ ràng của một vài dòng mã mà không thể tách ra thành các phần nhỏ hơn, hữu ích; một chức năng có thể được tái sử dụng trực tiếp hoặc khác bởi các chức năng khác.


5

Nếu nó phải rất nhanh, làm cho nó một bí danh hoặc một chức năng.

Nếu nó có thể sử dụng được bên ngoài lớp vỏ ưa thích của bạn, hãy biến nó thành tập lệnh. 1

Nếu nó có đối số, làm cho nó một hàm hoặc một tập lệnh.

Nếu nó cần chứa các ký tự đặc biệt, hãy đặt nó thành bí danh hoặc tập lệnh. 2

Nếu nó cần làm việc với sudo, hãy biến nó thành bí danh hoặc tập lệnh. 3

Nếu bạn muốn thay đổi nó dễ dàng mà không cần đăng xuất và đăng nhập, một tập lệnh sẽ dễ dàng hơn. 4

Chú thích

1 Hoặc biến nó thành bí danh, đặt nó vào ~/.envvà thiết lập export ENV="$HOME/.env", nhưng thật phức tạp để làm cho nó hoạt động tốt.

2 Tên hàm phải là mã định danh, vì vậy chúng phải bắt đầu bằng một chữ cái và chỉ có thể chứa các chữ cái, chữ số và dấu gạch dưới. Ví dụ, tôi có một bí danh alias +='pushd +1'. Nó không thể là một chức năng.

3 Và thêm bí danh alias sudo='sudo '. Ditto bất kỳ lệnh khác như strace, gdbvv mà phải mất một lệnh như là đối số đầu tiên của nó.

4 Xem thêm: fpath. Tất nhiên bạn cũng có thể làm source ~/.bashrchoặc tương tự, nhưng điều này thường có tác dụng phụ khác.


1
Tôi không biết bạn có thể bí danh +trong bash. Thật thú vị, sau khi thử nghiệm tôi phát hiện ra rằng trong bash bạn có thể tạo +bí danh nhưng không phải là hàm, như bạn nói, nhưng zsh là ngược lại - +có thể là một hàm nhưng không phải là bí danh.
Kevin

Trong zshbạn phải viết alias -- +='some command here'.
Mikel

Bằng cách nào đó, tôi không nghĩ răng cưa +là di động. Xem thông số kỹ thuật POSIX trên Tên bí danh
jw013

3
Upvote cho sudoviệc sử dụng. Về chú thích 4, tôi lưu trữ các bí danh của mình ~/.bash_aliasesvà định nghĩa hàm ~/.bash_functionsđể tôi có thể dễ dàng sử dụng lại sourcechúng (mà không có bất kỳ nguy hiểm nào về tác dụng phụ).
Anthony Geoghegan

3

Chỉ cần thêm một vài ghi chú:

  • Chỉ có thể sử dụng tập lệnh riêng biệt với sudo (như nếu bạn cần chỉnh sửa tệp hệ thống), ví dụ:
sudo v /etc/rc.conf  #where v runs vim in a new terminal window;
  • Chỉ các bí danh hoặc hàm mới có thể thay thế các lệnh hệ thống dưới cùng tên (giả sử rằng bạn thêm tập lệnh của bạn vào cuối PATH, điều mà tôi nghĩ là nên dùng để đảm bảo an toàn trong trường hợp tạo tập lệnh ngẫu nhiên hoặc không chính xác với tên giống với lệnh hệ thống), ví dụ:
alias ls='ls --color=auto'  #enable colored output;
  • Các bí danh và hàm mất ít bộ nhớ và thời gian để thực hiện, nhưng mất thời gian để tải (vì shell phải diễn giải tất cả trước khi hiển thị cho bạn lời nhắc). Hãy tính đến điều này nếu bạn chạy các quy trình shell mới thường xuyên, ví dụ:
# pressing key to open new terminal
# waiting for a few seconds before shell prompt finally appears.

Ngoài ra, bạn có thể sử dụng hình thức đơn giản nhất có thể, tức là trước tiên hãy xem xét bí danh, sau đó là chức năng, sau đó là tập lệnh.


5
Bí danh cũng có thể được sử dụng với sudo. Nhưng trước tiên bạn cần alias sudo='sudo '.
Mikel

Mặc dù đúng là việc thực thi một tập lệnh sẽ tiêu tốn nhiều bộ nhớ hơn trong suốt thời gian của fork + exec, việc có rất nhiều mã được nạp vào bộ nhớ của phiên bản shell hiện tại khiến nó tiêu tốn nhiều bộ nhớ hơn về phía trước, thường để lưu trữ mã mà chỉ lưu trữ được sử dụng khá hiếm.
tripleee

2

Nguyên tắc của tôi là:

  • bí danh - một lệnh, không có tham số
  • chức năng - một lệnh một số tham số
  • script - một số lệnh, không có tham số

1

Trong môi trường nhiều người dùng (hoặc đa sysamin), tôi sử dụng các tập lệnh cho tất cả mọi thứ, ngay cả khi nó chỉ là một trình bao bọc 'thực hiện một cái gì đó ....' ngắn.

Chắc chắn, về mặt kỹ thuật chậm / kém hiệu quả hơn so với bí danh hoặc chức năng, nhưng điều đó hầu như không bao giờ quan trọng - và miễn là trong đường dẫn, một kịch bản luôn hoạt động.

Tính năng của bạn có thể được gọi từ cron, từ thứ gì đó có môi trường bị giảm hoặc sửa đổi như sudo hoặc env hoặc người dùng có thể đang sử dụng một vỏ khác cho bạn - tất cả hoặc có khả năng phá vỡ bí danh hoặc chức năng.

Nếu bạn có một cái gì đó nhạy cảm về hiệu năng, hãy xử lý nó như một trường hợp đặc biệt hoặc tốt hơn nữa, hãy xem xét rằng một kích hoạt để viết lại bằng ngôn ngữ kịch bản chức năng hơn.

Nếu chúng ta đang nói về các tính năng sẽ chỉ được sử dụng trong các tập lệnh khác, thì bạn cũng có thể xem xét việc xác định trình bao chuẩn và viết tập lệnh thư viện hàm có thể có. Tôi có nguồn gốc cho tất cả các kịch bản khác.

T


0

Một ví dụ cho một tình huống mà bạn rất có thể muốn sử dụng Bí danh.

Tôi biết đây là một bài viết cũ nhưng tôi muốn chỉ ra một tình huống mà tôi gần như phải sử dụng kết hợp bí danh với một tập lệnh và tôi đã chọn không sử dụng một chức năng.

Tôi có một đoạn script ~/.bin/được gọi setupnhư sau: 1

  1. đưa tôi đến một thư mục nhất định.
  2. định nghĩa một vài biến.
  3. in thông điệp về trạng thái của thư mục. 2

Vấn đề là nếu tôi chỉ chạy, setup <project-name>tôi sẽ không xác định được các biến đó và tôi sẽ không nhận được thư mục nào cả. Giải pháp tôi thấy là tốt nhất là thêm tập lệnh này vào PATHvà thêm alias setup=". ~/.bin/setup"vào ~/.bashrchoặc bất cứ điều gì.

Ghi chú:

  1. Tôi đã sử dụng một tập lệnh cho tác vụ này và không phải là một chức năng không phải vì nó đặc biệt dài mà vì tôi có thể chỉnh sửa nó và tôi không phải lấy nguồn tệp sau khi chỉnh sửa nếu tôi muốn làm mới việc sử dụng nó.
  2. Một trường hợp tương tự đã xảy ra với tôi khi tôi tạo một tập lệnh để tải lại tất cả các dotfiles của mình. 3
  1. Kịch bản có sẵn trong kho lưu trữ dotfiles của tôi dưới .bin/.
  2. Về kịch bản : Tôi cung cấp cho kịch bản này một đối số là tên của dự án mà tôi đã xác định trước. Sau đó, tập lệnh biết đưa tôi đến đúng thư mục theo một csvtệp nhất định . Các biến nó định nghĩa được lấy từ makefile trong thư mục đó. Kịch bản chạy sau đó ls -lgit statusđể cho tôi thấy những gì đang xảy ra ở đó.
  3. Kịch bản đó cũng có sẵn trong kho lưu trữ dotfiles của tôi .bin/.

1
Hừm, dường như đó chỉ là một chức năng, không phải là sự kết hợp bí danh. (BTW, các môi trường được đánh vần là "môi trường" chứ không phải "enviorments.")
Wildcard

Cảm ơn đã bình luận về lỗi đánh máy, tôi sẽ sửa nó trong lần xác nhận tiếp theo. Đối với việc sử dụng một hàm thay vì một tập lệnh - có lẽ tôi sẽ sử dụng một hàm cho tác vụ cụ thể này và bỏ các bí danh này. Vấn đề là đôi khi khá dễ sử dụng tập lệnh và bí danh nếu thỉnh thoảng bạn chỉnh sửa tập lệnh đó .
Doron Behar

0

Khi nào viết kịch bản

Khi bạn có thể muốn chạy lệnh từ một công cụ khác ngoài shell.

Điều này bao gồm vim (đối với tôi): có các bộ lọc bằng văn bản và các chương trình khác dưới dạng tập lệnh, tôi có thể làm gì đó :%!my-filterđể lọc một tệp thông qua chương trình từ trình chỉnh sửa của mình.

Nếu my-filterlà một hàm hoặc bí danh, điều đó sẽ không thể thực hiện được.

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.