Tại sao có / bin / echo và tại sao tôi muốn sử dụng nó?


52

Tôi nhận thấy rằng có một tệp thực thi nhị phân /bin/echotrên hệ thống Ubuntu MATE 17.04 của tôi.

Tôi nghĩ, đó là kỳ lạ, bởi vì

$ type echo
echo is a shell builtin

Thử nghiệm chữ thảo cho thấy điều đó /bin/echocũng giống như cách xây dựng Bash echo:

$ /bin/echo foo
foo
$ /bin/echo $USER
zanna

Vậy, tại sao lại có một phiên bản khác echotách biệt với chương trình Bash, và tại sao hoặc khi nào tôi muốn sử dụng nó?



2
@ bodhi.zazen Điều đó khá hữu ích mặc dù nó không giống nhau, bởi vì nó giải quyết vấn đề ngược lại của câu hỏi này. Câu hỏi đó hỏi tại sao echođược cung cấp dưới dạng shellin, trong khi câu hỏi này hỏi tại sao nó được cung cấp dưới dạng lệnh bên ngoài.
Eliah Kagan

3
Một lý do là không phải ai cũng sử dụng bash. Tôi đoán rằng / bin / echo có trước bash và các nhà phát triển thấy nó hữu ích / hiệu quả khi đưa nó vào dưới dạng tích hợp thay vì sử dụng tệp thực thi.
jamesqf

Câu trả lời:


87

Nếu bạn mở một bashdấu nhắc và gõ echolệnh, sử dụng shell dựng sẵn thay vì chạy /bin/echo. Những lý do vẫn còn quan trọng /bin/echođể tồn tại là:

  1. Bạn không phải lúc nào cũng sử dụng vỏ. Trong nhiều trường hợp, bạn chạy một tệp thực thi trực tiếp và không thông qua trình bao.
  2. Ít nhất là trên lý thuyết, một số vỏ không có tích hợp echo. Điều này không thực sự cần thiết.

Mở rộng trên # 1, giả sử bạn muốn di chuyển tất cả các tập tin thường xuyên có tên bắt đầu với abcbất cứ nơi nào trong srcđể dest. Có một số cách để làm điều đó nhưng một trong số đó là:

find src -name 'abc*' -type f -exec mv -nv {} dest/ \;

Nhưng giả sử, thay vì chỉ chạy nó, bạn muốn xem mọi lệnh sẽ được chạy trước. Chà, sau đó bạn có thể thêm vào echolệnh, giống như bạn có thể trong các bối cảnh khác:

find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;

Nhưng findkhông sử dụng vỏ. Mà chạy /bin/echo.

Ngoài ra findvới -exechoặc-execdir , chương trình /bin/echothực thi sẽ được gọi bởi các chương trình khác tự chạy chương trình nhưng không thông qua trình bao. Đây sẽ xảy ra với các xargslệnh (mà có liên quan đến find), cũng như trong một số bối cảnh khác, chẳng hạn như các Exec=dòng của một .desktoptập tin . Một ví dụ khác là khi bạn chạy sudo echo, có thể thuận tiện cho việc kiểm tra nếu sudođang hoạt động.

Tương tự, một số shell có tích hợp printfnhưng /usr/bin/printfcũng tồn tại.

Một lý do ít phổ biến hơn có thể bạn có thể cố tình sử dụng /bin/echolà nếu bạn đang dựa vào sự khác biệt giữa nó và echolệnh được cung cấp bởi shell của bạn. man echotài liệu /bin/echo; help echotrong bash tài liệu bashdựng sẵn. echokhông dễ mang theo, bởi vì các cách triển khai khác nhau - cả trên các hệ điều hành và trên các hệ vỏ trên cùng một hệ điều hành - hỗ trợ các tùy chọn khác nhau (ví dụ -e:) và khác nhau trong cách xử lý dấu gạch chéo ngược . Tất nhiên, tốt hơn hết là tránh dựa vào các chi tiết như vậy và sử dụng printfthay vào đó, tính di động cao hơn nhiều .

Trong bash, bạn cũng có thể tạo typechương trình dựng sẵn /bin/echo- giả sử /binlà trong bạn $PATHnhư mọi khi - bằng cách chuyển -acờ :

$ type -a echo
echo is a shell builtin
echo is /bin/echo

21
Và cũng bởi vì đặc tả POSIX nói rằng phải có một.
glenn jackman

4
@glennjackman Tôi đã hy vọng ai đó sẽ đăng câu trả lời về điều đó, thực sự, và tôi hy vọng bạn quyết định làm như vậy! Mặc dù vậy, có một số sự tinh tế liên quan, vì cả Debian, Ubuntu, hay GNU Coreutils (cũng không phải toàn bộ Dự án GNU) đều cố gắng tuân thủ POSIX trong mọi thứ . Ví dụ, POSIX khẳng định cdtồn tại thực thi (khi chạy, thay đổi thư mục và thoát, để lại người gọi ở trước đó) và một số HĐH có một. Có thể hữu ích khi trích dẫn 4.1 trong các tiêu chuẩn GNU .
Eliah Kagan

@EliahKagan: Incidentaly / usr / bin / cd có một lệnh sử dụng: / usr / bin / cd lệnh chạy lệnh đó trong thư mục đó. Nếu thay đổi thư mục không thành công, lệnh không bắt đầu.
Joshua

4
@Joshua sử dụng tốt hơn cdchỉ đơn giản là kiểm tra khả năng truy cập vào một thư mục nhất định: nếu /usr/bin/cd some/dirthành công, trong một lần chụp bạn đã kiểm tra: a) some/dirtồn tại, b) đó là thư mục hoặc liên kết đến một và c) quyền cần thiết để bạn truy cập thư mục đó tồn tại; tất cả mà không thay đổi trạng thái của riêng bạn.
muru

1
@CarlWitthoft, xem Tại sao printf tốt hơn echo? Ngoài ra /bin/echo, không \bin\echo, trừ khi bạn đang sử dụng Windows. ;)
tự đại diện

31

Eliah đã làm rất tốt khi trả lời điều này, nhưng tôi muốn bình luận về phần "tại sao lại có một phiên bản khác echotách biệt với chương trình Bash". Đó là câu hỏi sai.

Câu hỏi đúng là: tại sao đây là một dựng sẵn ở nơi đầu tiên , khi nó có thể là (và là) một lệnh bên ngoài hoàn toàn tốt?

Để đơn giản, hãy xem các nội trang trong dấu gạch ngang, một con số 38 (bash có 61, để so sánh, đi theo đầu ra của compgen -b):

.               continue        getopts         readonly        type
:               echo            hash            return          ulimit
[               eval            jobs            set             umask
alias           exec            kill            shift           unalias
bg              exit            local           test            unset
break           export          printf          times           wait
cd              false           pwd             trap
command         fg              read            true

Có bao nhiêu trong số này cần phải được xây dựng? [, echo, false, printf, pwd, test, Và truekhông cần phải dựng sẵn: Họ không làm gì cả mà chỉ có một dựng sẵn có thể làm (ảnh hưởng hoặc có được trạng thái vỏ đó là không có sẵn cho các lệnh bên ngoài). Bash's printfít nhất tận dụng lợi thế của một tích hợp: printf -v varlưu đầu ra vào biến var. timetrong bash cũng đặc biệt: bằng cách là một từ khóa, bạn có thể liệt kê các danh sách lệnh tùy ý trong bash (dấu gạch ngang không có timetương đương). pwdcũng không cần phải là một nội dung - bất kỳ lệnh bên ngoài nào cũng sẽ kế thừa thư mục làm việc hiện tại (và đó cũng là một lệnh bên ngoài ).:là một ngoại lệ - bạn cần một NOP, và :nó là như vậy. Phần còn lại thực hiện các hành động mà một lệnh bên ngoài có thể dễ dàng thực hiện.

Vì vậy, một phần năm trong số các bản dựng này không cần phải là bản dựng. Tại sao, sau đó? Các dashmanpage * thực sự giải thích trong đi qua tại sao đây là lệnh nội trú (tôi nhấn mạnh):

Nội địa
 Phần này liệt kê các lệnh dựng sẵn được xây dựng bởi vì chúng
 cần thực hiện một số thao tác không thể được thực hiện bởi một riêng
 quá trình. Ngoài những thứ này, có một số lệnh khác có thể
 được xây dựng cho hiệu quả (ví dụ printf (1), echo (1), test (1), v.v.).

Đó là khá nhiều: các nội dung này có ở đó bởi vì chúng được sử dụng thường xuyên, tương tác và trong các tập lệnh, và chức năng của chúng đủ đơn giản, để trình bao có thể thực hiện công việc. Và như vậy nó sẽ xảy ra: một số (? Nhất) vỏ mất trong công việc ** Quay trở lại. Cácsh từ 2,9 BSD , và bạn sẽ không tìm thấy một echodựng sẵn.

Vì vậy, hoàn toàn có khả năng một shell tối thiểu có thể bỏ qua việc thực hiện các lệnh như nội dung (tuy nhiên tôi không nghĩ rằng bất kỳ shell hiện tại nào cũng vậy). Dự án coreutils GNU không cho rằng bạn sẽ chạy chúng trong một trình bao cụ thể và POSIX yêu cầu các lệnh này. Vì vậy, coreutils cung cấp những thứ này dù sao đi nữa, và bỏ qua những thứ không có ý nghĩa gì ngoài vỏ.


* Điều này gần giống với văn bản trang chủ tương ứng cho trình bao Almquist , đó là những gì dấu gạch ngang, trình bao của Debian Almquist, dựa trên.

** zshđưa ý tưởng này đến mức cực đoan: các lệnh bạn nhận được bằng cách tải các mô-đun khác nhau, như zmv, là những thứ bạn không nghĩ rằng cần phải có vỏ . Tại thời điểm đó, câu hỏi thực sự là: tại sao bạn sẽ sử dụng bash thay vì zsh, nơi có tất cả các nội dung này?


1
Nó chỉ ra rằng: cũng không cần phải là một nội dung. Thật là ngớ ngẩn khi nó không phải là một nội dung. Trừ khi bạn đang đối phó với các vấn đề cấp độ đĩa mềm cứu hộ ban đầu (trong trường hợp đó tôi phát hiện ra cách khó khăn mà pwd không hoạt động đáng tin cậy), hình phạt duy nhất cho việc không có này là tích hợp là hiệu suất khủng khiếp.
Joshua

5
@Joshua không, :vì bên ngoài sẽ không thực sự là NOP, bạn vẫn sẽ PATHtra cứu, cố gắng thực thi lệnh, v.v., khi tất cả những gì bạn thực sự muốn là không làm gì cả. :như một nội dung làm điều đó.
muru

2
Bash thực sự cần pwdphải được tích hợp sẵn để nó hoạt động theo cách của nó, với hành vi mặc định hiển thị đường dẫn "logic" ( pwd -L). /bin/pwdchỉ có thể thực hiện pwd -Phành vi hiển thị cho bạn các thư mục cha mẹ thực tế, không thể liên kết tượng trưng mà bạn đã duyệt cdqua.
Peter Cordes

2
pwdTrạng thái của @PeterCordes bị tổn hại đôi chút bởi sự hiện diện của PWD, nhưng vâng, đó cũng là một trường hợp sử dụng trạng thái dựng sẵn để cải thiện chức năng
muru
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.