Hãy bắt đầu mọi lệnh bằng dấu phẩy (2009)
(rhodesmill.org)- Người dùng Unix thường đặt các script cá nhân vào
~/bin/và thêm vàoPATH, nhưng các tên lệnh ngắn có thể xung đột với lệnh hệ thống mới - Trong môi trường có nhiều lệnh được cung cấp như Debian/Ubuntu, rủi ro này còn lớn hơn; ví dụ trên một laptop Ubuntu, số lệnh trong
/usr/binđược thống kê là 21.733 - Nếu thêm dấu phẩy (
,) vào trước lệnh cá nhân, shell và các công cụ sẽ coi đó là ký tự tên tệp thông thường, đồng thời dễ phân biệt với lệnh hệ thống - Dấu phẩy có thể gõ mà không cần Shift, và ít khả năng gây xung đột hơn ngoặc, dấu gạch chéo ngược, dấu hai chấm, dấu backtick, dấu nháy đơn, dấu gạch chéo và dấu chấm vốn mang ý nghĩa mạnh trong shell
- Nhấn Tab sau
,cho phép duyệt ngay danh sách lệnh cá nhân, giúp giữ cho tên lệnh trong~/bin/gọn gàng hơn
Vì sao tên lệnh cá nhân bị xung đột
- Nhiều người dùng Unix tạo
~/bin/trong thư mục home và thêm nó vàoPATHđể dùng các lệnh tiện ích cá nhân và shell script - Vấn đề là tên script cá nhân thường là các tổ hợp chữ thường ngắn, nên rất dễ giống với lệnh hệ thống mặc định
- Khi bản phân phối Linux thêm lệnh mới, tên của nó có thể tình cờ trùng với lệnh cá nhân đang có
- Trong môi trường họ Debian, số lượng lệnh được cung cấp rất lớn nên vấn đề này càng thực tế hơn
- Trên một laptop Ubuntu mẫu, khi đếm số lệnh ngay dưới
/usr/binthì ra21,733 apt-file search -x '^/usr/bin/[^/]*$' | wc -l
- Trên một laptop Ubuntu mẫu, khi đếm số lệnh ngay dưới
Lợi ích của tiền tố dấu phẩy
- Giải pháp là đổi tên lệnh cá nhân sang một dạng vừa dễ gõ vừa khó bị chọn làm tên lệnh hệ thống
- Tiêu chí về sự tiện khi gõ là không cần dùng phím Shift, và với điều kiện này thì không có nhiều ký tự an toàn để chọn
- Chữ thường đã được dùng rất phổ biến trong lệnh hệ thống
- Ngoặc, dấu gạch chéo ngược, dấu hai chấm, dấu backtick và dấu nháy đơn đều có ý nghĩa đặc biệt trong shell
- Dấu gạch chéo là ký tự phân tách thư mục nên không thể nằm trong tên tệp
- Dấu chấm ở đầu tên tệp biểu thị tệp ẩn, và ở vị trí khác cũng thường được dùng để phân tách phần mở rộng
- Lựa chọn còn lại đơn giản là dấu phẩy (
,), và các công cụ xung quanh cùng shell đều xử lý dấu phẩy như một ký tự thông thường trong tên tệp - Nếu thêm dấu phẩy làm tiền tố cho từng lệnh cá nhân, chúng sẽ được phân biệt rõ với lệnh hệ thống và dễ tránh xung đột tên hơn
- Khi dùng cùng Tab completion, chỉ cần gõ
,là có thể xem ngay danh sách lệnh cá nhân- Danh sách ví dụ gồm
,complete-scp,,complete-ssh,,coreoff,,coreon,,find,,go-thpgp,,gr,,hss,,mount-thpgp,,mount-twt,,range,,svn-store-password,,umount
- Danh sách ví dụ gồm
- Cách này đã được dùng trong khoảng 10 năm và được khuyến nghị như một phương pháp giữ cho các tên lệnh trong
~/bin/sạch sẽ, ngăn nắp
2 bình luận
Các ý kiến trên Hacker News
Chỉ nhìn tiêu đề thì tôi tưởng đây sẽ là một ý tưởng khủng khiếp, nhưng thực ra tôi lại khá thích. Đặc biệt tôi thích phần liệt kê toàn bộ công cụ của mình bằng phím Tab
Gần đây tôi không gặp nhiều xung đột namespace, và đúng là sau khi chuyển sang vai trò quản lý thì cảm giác kỹ thuật của tôi cũng hơi lỏng đi. Tech stack của tôi có cảm giác lỗi thời khoảng 10 năm, nên tôi tự hỏi nên bắt đầu từ đâu để bắt kịp lại cảm giác hiện đại
Cách tôi làm là tự tạo các công cụ giúp cuộc sống của mình dễ hơn. Ví dụ, nếu ở công ty có một web service tôi thường dùng cho các truy vấn đơn giản, tôi sẽ xem nó có API không và viết CLI để làm nhanh các tác vụ hằng ngày. Sau khi tinh chỉnh cho ưng ý, tôi chia sẻ với nhóm, nhưng thuyết phục người khác dùng thử thì khó thật. Dù vậy tôi dùng nó mỗi ngày nên cũng không quá bận tâm
Mục đích là để thấy góc nhìn mới và có thể trò chuyện về các xu hướng; một phần trong số đó giờ cũng đã chuyển sang công việc. Nhờ vậy tôi cũng hiểu sâu hơn về các thành phần cũ
Tôi không thật sự hiểu vấn đề này. Chỉ cần đặt thư mục
bincủa tôi ở đầu$PATHthay vì cuối là được. Muốn xem các lệnh của mình thì cứ chạyls ~/bin$0nằm trong đường dẫn hệ thống, nhưng điều đó bị phá vỡ và bắt đầu một màn debug bực bộiCuối cùng chỉ là chọn loại độc nào thôi
fzf. Ví dụ trong fish, bạn có thể gõ chữ cái đầu của lệnh rồi nhấn Tab để mởfzfKhi đó chỉ với
,+Tab là có thể nhanh chóng lọc các lệnh tùy chỉnh. Trong khi đóls ~/binthì cần gõ nhiều ký tự đối với một việc làm thường xuyên, hoặc có thể phải dùngls+mũi tên lên nhiều lần để tìm lại phần tự động hoàn thành trước đóls ~/binchậm hơn,rất nhiềuTôi dùng các tên lệnh tùy chỉnh ngắn như
aa,st,di,dp,cm,lecho một wrapper mỏng quanhgitMột trong số đó thực sự xung đột với một tiện ích được cài mặc định trên hệ thống nào đó. Nhưng vì thư mục
bincủa tôi đứng trước các thư mục hệ thống trong$PATH, cái của tôi thắng, và tôi cũng không mấy quan tâm đến công cụ bị xung đột đó. Nếu một công cụ khác hữu ích với tôi xung đột với công cụ của tôi, có lẽ tôi sẽ đặt cho công cụ kia một alias không xung đột hơn là đổi tên công cụ của mình. Những công cụ hai chữ cái này quá tiệnapt-get upgradelại chạy Dwarf Fortresshttps://askubuntu.com/questions/938606/dwarf-fortress-starti...
gitcủa tôi thường là các tổ hợp hai chữ cái bắt đầu bằngg. Ví dụgslàgit statusNhưng đôi khi tôi thật sự cần GhostScript. Nó rất tuyệt trong những trường hợp như nhúng phông chữ vào file PDF. Thường khi đó tôi dùng
env gsj. Khijavaxuất hiện thì chuyện trở nên khá thú vị. Dùng dấu phẩy là một ý tưởng khá thú vịDù sao cũng may là tôi không bắt đầu bằng
k, vì KDE :)Ví dụ tôi nghĩ
mkfsnên được gọi kiểu nhưsys::mkfs. Ranh giới giữa lệnh hệ thống và lệnh người dùng có thể được định nghĩa theo nhiều cách và cũng sẽ có chỗ mơ hồ, nhưng nếu người dùng có thể vô tình chạy một lệnh mà họ thậm chí không biết vì sao nó tồn tại và cũng chưa từng cài đặt rõ ràng, thì lệnh đó không nên được phơi bày trực tiếp trong namespace toàn cụcCó một câu hỏi liên quan
Tôi chủ yếu dùng Windows, và giống tác giả, tôi tạo nhiều script CLI xoay quanh Python rồi đặt ở nơi tương đương
~/bin/. Nếu đặtpython.exelàm chương trình mặc định cho phần mở rộng.pyvà thêm.pyvào%pathext%, thì từ bất kỳ đường dẫn nào tôi cũng có thể chỉ gõhellođể chạy~/bin/hello.py, và tôi dùng như vậy hàng trăm lần mỗi ngày. Dạo này tôi dùng Linux nhiều hơn, nhưng vẫn còn là người mới nên chưa làm được theo cùng cách đó. Có vẻ Linux không có khái niệm “chương trình được liên kết”, nên không thể gọi thẳng file.pyrồi để shell chạy nó bằng Python. Tất nhiên có thểchmod +xcho script, nhưng như vậy phải đặt shebang trong chính script, cảm giác như hard-code nên không thoải mái. Tôi tự hỏi sau này nếu muốn chạy script.pybằng/usr/bin/nohtypthay vì/usr/bin/pythonthì sao. Hơn nữa tôi cũng không tìm được cách bỏ phần.pykhi gọi script. Tôi không có ý phê phán thiết kế của Linux, và tôi biết nó có nhiều ưu điểm, nhưng tôi thật sự muốn chạyhello.pynằm trong$PATHbằng tênhellomy_pythontrong một thư mục thuộc đường dẫn, rồi viết shebang là/usr/bin/env my_pythonNếu muốn cách tiếp cận bài bản hơn, hãy xem công cụ
update-alternatives. Nó cung cấp kiểu trừu tượng này một cách tổng quát hơn: https://linuxconfig.org/how-to-set-default-programs-using-up...Trên Linux, thật ra là trên hầu hết các nền tảng ngoài Windows, ý nghĩa của phần mở rộng file yếu hơn nhiều. Bất kỳ loại file thực thi nào cũng được xác định khả năng chạy không phải bằng phần mở rộng, mà bằng cờ như
+x. Nhờ vậy, bạn có thể viết lại bằng ngôn ngữ triển khai khác mà không làm hỏng phía gọi. Phần mở rộng.pychỉ thật sự có ý nghĩa với các module được import để dùng; còn nếu là script được thực thi thì khi cần chỉ cần nhìn shebang. Script phân phối bên ngoài thường dùng#!/usr/bin/env python, còn script đi kèm gói của bản phân phối thì sẽ được ghi đè thành kiểu#!/usr/bin/python. Ngoài ra shebang không hỗ trợ nhiều đối số, nhưng GNUenvhỗ trợ đối số-Sđể mô phỏng việc đó. Tuy nhiên vấn đề độ dài đối số vẫn còn.pykhỏi tên file là được. Gọi nó là"hello"là hoàn toàn ổnTôi không nghĩ ra nhược điểm nào đáng kể của shebang. Nếu thật sự muốn chạy bằng trình thông dịch khác thì có thể chỉ rõ như
"nohtyp hello". Nếu vẫn thấy quá khó chịu, bạn có thể định nghĩa alias trong file khởi động shell. Ví dụ trong bash có thể làmalias hello="python3 /path/to/hello.py". Nếu muốn, bạn cũng có thể viết một script ngắn tự động tạo các alias như vậy cho nội dung của một thư mục chỉ địnhTrong script shell, thông thường ta thêm shebang và làm file có thể thực thi, tức là khai báo file thực thi ngay trong chính script. Có thể nghĩ shebang như một dạng phần mở rộng file. Nếu sau
chmod +x ./malware.pymà./malware.pykhông chạy, hãy kiểm tra đường dẫn mà shebang trỏ tới. Nếu trình thông dịch có thể chạy script như một đối số thông thường, thì cũng có thể tạo hành vi tương tự bằng cách nhưxdg-open malware.py. Nó sẽ giống như nhấp đúp trong trình quản lý file mặc định. Khi dùng Linux làm hệ điều hành desktop chính, tôi từng đặt aliasxop, nhưng chỉ dùng cho các file dữ liệu như ảnh hoặc tài liệu vốn đã có hành vi mặc định phù hợp. Tôi không khuyến nghị đặt chương trình mặc định của script có thể thực thi thành trình thông dịch. Theo mặc định, có thể bạn muốn mở script trong trình soạn thảo thay vì chạy nó. Tôi nghĩxdg-openlà công cụ phía Gnome, nhưng không có nghĩa là không dùng được trên desktop khác; tôi cũng đã dùng nó trên Xubuntu. Nếu thật sự muốn tất cả file Python mặc định chạy trong cả ngữ cảnh GUI, bạn có thể đặt mặc định như vậy, nhưngman xdg-opencó thể hữu ích. Nhắc lại, đây không phải lời khuyên hay#!/usr/bin/env pythonNhư vậy
pythonđầu tiên tìm thấy trong đường dẫn sẽ được chạy. Nếu sau này muốn chạy bằng/usr/bin/nohtypthay vì/usr/bin/python, bạn có thể tạo một liên kết tượng trưng tênpythontrỏ tới/usr/bin/nohtyptrong một thư mục được tìm kiếm trước/usr/bin. Ví dụ thêm~/myCommandPreferencesvào đầu$PATHMột cách khác để tránh xung đột
$PATHlà đặt tên file thực thi thật dài, rất ít khả năng file thực thi khác dùng tới, rồi tạo alias ngắn trongbashrcAlias không ảnh hưởng tới các file thực thi được gọi bên trong script, còn trong script của tôi thì tôi vẫn có thể tiếp tục tham chiếu bằng tên dài. Nhược điểm là không có được cùng mức tiện dụng của tự động hoàn thành bằng phím Tab, mà phần đó thì thật sự rất hay. Ngoài ra, với các script phải được
sourcechứ không chạy thành tiến trình con, như script kích hoạtvenvcủa Python, vẫn có thể xảy ra xung đột, nhưng những trường hợp như vậy hiếmzshthì phần tự động hoàn thành đó cũng làm đượcCách bắt đầu bằng dấu phẩy cũng là một kỹ thuật phổ biến trong cộng đồng trình mở rộng văn bản/thay thế văn bản
,Gần đây khi xem
~/.local/bin/, tôi phát hiện có hàng chục file thực thi mà tôi không nhớ mình đã đặt vàoPhần lớn liên quan đến pyside, nhưng cũng có các script khác. Tôi phải mở từng cái để nhớ script nào là do mình tự viết và cái nào là của người khác. Nếu tên script của tôi bắt đầu bằng dấu phẩy thì việc đó đã nhanh hơn nhiều, và cũng giúp tôi nhớ ra vì sao mình tạo từng script trước khi mở chúng
~/.local/bin/dành cho các script đã được cài đặt, còn những thứ tự viết cục bộ thì đặt trong~/bin/Xin phép không dùng. Chỉ cần đặt
bincá nhân ở đầu$PATH, và khi tham chiếu đến chương trình bị che khuất thì dùng/usr/binhoặc/binlà đượcCó thể liệt kê danh sách công cụ đã cá nhân hóa bằng
~/bin/[Tab]Nếu tôi không thích
grepcủa hệ thống, ví dụgreptrên Solaris, và muốn dùng GNUgrepmà tôi ưa thích, thì sao không cứ để nó làgrep?Nhờ biết ý tưởng này 5 năm trước mà tôi đã sắp xếp được bộ mẹo shell của mình có trật tự hơn. Gộp alias và
~/binlại, tôi có hơn 50 lệnh dấu phẩy, và đời sống shell trở nên trơn tru hơn nhiều so với tình trạng lộn xộn trước đâyNăm 2020 cũng từng có thảo luận: https://news.ycombinator.com/item?id=22778988 (90 bình luận)
, macroexpandStart all of your commands with a comma (2009) - https://news.ycombinator.com/item?id=31846902 - tháng 6 năm 2022 (121 bình luận)
Start all of your commands with a comma (2009) - https://news.ycombinator.com/item?id=22778988 - tháng 4 năm 2020 (89 bình luận)
Dùng
'_'thì sao?