10 cách sử dụng ký hiệu hoặc toán tử (!) trong các lệnh Linux

Trong Linux, ký hiệu hoặc toán tử '!' có thể được sử dụng như toán tử phủ định Logic cũng như để lấy các lệnh từ lịch sử với những thay đổi hoặc chạy lệnh đã chạy trước đó với sự thay đổi. Tất cả các lệnh dưới đây đã được kiểm tra rõ ràng trong Shell bash và hầu hết chúng sẽ không chạy trên các shell khác. Dưới đây là một số cách sử dụng ký hiệu hoặc toán tử '!' trong các lệnh Linux.

Chạy một lệnh từ lịch sử bằng số lệnh

Bạn có thể chạy một lệnh từ lịch sử của bạn (các lệnh đã được thực thi trước đó). Để bắt đầu, tìm số lệnh bằng cách chạy lệnh 'history'. Sau đó, chạy một lệnh từ lịch sử chỉ bằng số xuất hiện của nó trong kết quả lệnh 'history'. Ví dụ, chạy lệnh xuất hiện ở số 1551 trong kết quả của lệnh 'history'. 

$ history

Nó sẽ chạy lệnh (trong trường hợp trên là lệnh 'top') được liệt kê ở số Cách này rất hữu ích để lấy lại các lệnh đã thực thi trước đó, đặc biệt là đối với các lệnh dài. Bạn chỉ cần gọi nó bằng cách sử dụng ![Số tại đó nó xuất hiện trong kết quả của lệnh 'history'].

$ !1551

Chạy lệnh đã thực thi trước đó như lệnh thứ hai từ cuối, lệnh thứ bảy từ cuối,...

Bạn có thể chạy các lệnh đã chạy trước đó bằng cách sử dụng thứ tự chạy của chúng, trong đó lệnh chạy cuối cùng được biểu diễn là -1, lệnh thứ hai từ cuối là -2, lệnh thứ bảy từ cuối là -7, ...

Đầu tiên chạy lệnh 'history' để có danh sách các lệnh đã thực thi gần đây nhất. Việc chạy lệnh 'history' là cần thiết để bạn có thể đảm bảo không có lệnh như 'rm command > file' và các lệnh khác không chạy nhầm các lệnh nguy hiểm.

Sau đó, bạn có thể kiểm tra lệnh thứ sáu từ cuối danh sách, lệnh thứ tám từ cuối danh sách và lệnh thứ mười từ cuối danh sách bằng cách sử dụng ký hiệu '-' kết hợp với số thứ tự của lệnh.

$ history
$ !-6
$ !-8
$ !-10

Chuyển các đối số của lệnh trước đó sang lệnh mới mà không cần gõ lại

Giả sử bạn cần liệt kê nội dung của thư mục '/home/$USER/Binary/firefox', thực hiện lệnh sau:

$ ls /home/$USER/Binary/firefox

Sau đó, bạn nhận ra rằng bạn nên sử dụng lệnh 'ls -l' để xem file nào có quyền thực thi nhưng bạn không cần phải gõ lại toàn bộ lệnh đó. Bạn chỉ cần chuyển đối số cuối cùng từ lệnh trước sang lệnh mới bằng cách sử dụng '!$' như sau:

$ ls -l !$

Điều này sẽ thay thế '!$' bằng đối số cuối cùng của lệnh trước đó.

Xử lý hai hoặc nhiều đối số sử dụng (!)

Giả sử bạn đã tạo một tệp tin văn bản '1.txt' trên màn hình chính (Desktop) 

$ touch /home/avi/Desktop/1.txt

Và sau đó sao chép nó vào '/home/avi/Downloads' bằng lệnh cp với đường dẫn đầy đủ. Bây giờ chúng ta đã truyền hai đối số với lệnh cp. 

$ cp /home/avi/Desktop/1.txt /home/avi/downloads

Đối số đầu tiên là '/home/avi/Desktop/1.txt' và đối số thứ hai là '/home/avi/Downloads'. Bạn có thể xử lý chúng một cách khác nhau bằng cách thực thi lệnh echo với mỗi đối số. 

$ echo “1st Argument is : !^”
$ echo “2nd Argument is : !cp:2”

Lưu ý rằng đối số đầu tiên có thể được in ra bằng "!^", và các đối số còn lại có thể được in ra bằng "![Name_of_Command]:[Number_of_argument]".

Trong ví dụ trên, lệnh đầu tiên là 'cp' và cần in ra đối số thứ hai. Do đó, bạn có thể sử dụng "!cp:2". Nếu một lệnh nào đó, ví dụ như 'xyz', được chạy với 5 đối số và bạn muốn lấy đối số thứ tư, bạn có thể sử dụng "!xyz:4" và sử dụng nó theo ý muốn. Tất cả các đối số có thể được truy cập bằng "!*".

Thực thi lệnh trước đó dựa trên từ khóa

Chúng ta có thể thực thi lệnh đã thực thi trước đó dựa trên từ khóa. Dưới đây là một ví dụ:

$ ls /home > /dev/null [Command 1]
$ ls -l /home/avi/Desktop > /dev/null                 [Command 2]
$ ls -la /home/avi/Downloads > /dev/null                 [Command 3]
$ ls -lA /usr/bin > /dev/null         [Command 4]

Trong ví dụ trên, chúng ta sử dụng cùng một lệnh (ls) nhưng với các tùy chọn khác nhau và cho các thư mục khác nhau. Hơn nữa, chúng ta đã chuyển đầu ra của mỗi lệnh đến '/dev/null' vì chúng ta không cần xử lý đầu ra của lệnh và console vẫn sạch sẽ.

Bây giờ, chúng ta sẽ thực hiện lệnh đã chạy cuối cùng dựa trên từ khóa. 

$ ! ls [Command 1]
$ ! ls -l [Command 2]
$ ! ls -la [Command 3]
$ ! ls -lA [Command 4]

Kiểm tra kết quả và bạn sẽ ngạc nhiên khi thấy rằng bạn đang chạy các lệnh đã được thực hiện trước đó chỉ bằng từ khóa ls. 

Sức mạnh của toán tử !!

Bạn có thể chạy/điều chỉnh lệnh đã chạy cuối cùng bằng cách sử dụng (!!). Nó sẽ gọi lệnh đã chạy cuối cùng với sửa đổi/thay đổi trong lệnh hiện tại. Hãy xem ví dụ sau:

Chạy một lệnh one-liner để lấy địa chỉ IP riêng.

$ ip addr show | grep inet | grep -v 'inet6'| grep -v '127.0.0.1' | awk '{print $2}' | cut -f1 -d/

Bạn cần chuyển hướng đầu ra của đoạn mã trên vào một tệp ip.txt. Lúc này, bạn sẽ phân vân có nên gõ lại toàn bộ lệnh và chuyển hướng đầu ra vào một tệp không? Đáp án đơn giản là sử dụng phím UP để truy cập lại lệnh cuối cùng và thêm '> ip.txt' để chuyển hướng đầu ra vào tệp. 

$ ip addr show | grep inet | grep -v 'inet6'| grep -v '127.0.0.1' | awk '{print $2}' | cut -f1 -d/ > ip.txt

Nhờ vào phím UP đã điều hướng ở đây. Bây giờ, hãy xem xét tình huống dưới đây.

$ ifconfig | grep "inet addr:" | awk '{print $2}' | grep -v '127.0.0.1' | cut -f2 -d:

Ngay khi chạy đoạn mã, dấu nhắc bash trả về một lỗi với thông báo "bash: ifconfig: command not found", không khó để đoán ra rằng lệnh này được chạy với tư cách người dùng thường khi nó nên được chạy với quyền root.

Vậy giải pháp là gì? Rất khó để đăng nhập với quyền root và sau đó gõ lại toàn bộ lệnh đó! Ngoài ra, phím UP trong ví dụ trước không thể giúp được ở trường hợp này. Chúng ta cần gọi "!!" (không có dấu ngoặc kép), điều này sẽ gọi lại lệnh cuối cùng cho người dùng hiện tại. 

$ su -c “!!” root

Ở đây, "su" là lệnh chuyển người dùng sang root, "-c" là để chạy lệnh cụ thể với quyền của người dùng đó, phần quan trọng nhất là "!!" sẽ được thay thế bằng lệnh cuối cùng và lệnh đã chạy trước đó sẽ được thay thế ở đây. Đúng vậy! Bạn cần cung cấp mật khẩu root. 

Khi bạn chạy lệnh apt-get với quyền người dùng bình thường, chúng thường xuyên gặp lỗi nói rằng bạn không có quyền thực thi. 

$ apt-get upgrade && apt-get dist-upgrade

Xuất hiện lỗi nhưng đừng quá lo lắng, hãy thực hiện lệnh dưới đây:

$ su -c !!

Tương tự, khi người dùng không được ủy quyền thực hiện một tác vụ như vậy, bạn hãy chạy…

$ service apache2 start
or
$ /etc/init.d/apache2 start
or
$ systemctl start apache2

Rất tiếc, người dùng không được ủy quyền thực hiện công việc như vậy, vì vậy hãy chạy...

$ su -c 'service apache2 start'
or
$ su -c '/etc/init.d/apache2 start'
or
$ su -c 'systemctl start apache2'

Chạy một lệnh ảnh hưởng đến tất cả các tệp trừ tệp ![File_name]

Dấu ! (Phủ định logic) có thể được sử dụng để chạy lệnh trên tất cả các tệp/phần mở rộng trừ tệp mà đứng sau '!'.

  • Xóa tất cả các tệp từ một thư mục trừ tệp có tên là 2.txt.
$ rm !(2.txt)
  • Xóa tất cả các tệp có loại từ thư mục trừ tệp có phần mở rộng là 'pdf'.
$ $ rm !(*.pdf)

Kiểm tra xem một thư mục (ví dụ: /home/avi/Tecmint) có tồn tại hay không? 

In ra nếu thư mục đó tồn tại hoặc không tồn tại. Ở đây, chúng ta sử dụng '! -d' để xác minh xem thư mục có tồn tại hay không, theo sau là toán tử AND Logic (&&) để in ra rằng thư mục không tồn tại và toán tử OR Logic (||) để in ra rằng thư mục tồn tại.

Logic là khi đầu ra của [ ! -d /home/avi/Tecmint ] là 0, nó sẽ thực thi những gì nằm sau AND Logic, ngược lại nó sẽ đi vào HOẶC Logic (||) và thực thi những gì nằm sau OR Logic.

$ [ ! -d /home/avi/Tecmint ] && printf '\nno such /home/avi/Tecmint directory exist\n' || printf '\n/home/avi/Tecmint directory exist\n'

Kiểm tra xem một thư mục có tồn tại hay không? Nếu không, thoát khỏi lệnh

Tương tự với điều kiện trên nhưng ở đây nếu thư mục mong muốn không tồn tại nó sẽ thoát khỏi lệnh.

$ [ ! -d /home/avi/Tecmint ] && exit

Tạo một thư mục (ví dụ: test) trong thư mục chính của bạn nếu nó chưa tồn tại.

Đây là một triển khai chung trong Scripting Language, nơi nếu thư mục mong muốn không tồn tại, nó sẽ tạo một thư mục mới.

[ ! -d /home/avi/Tecmint ] && mkdir /home/avi/Tecmint

Bên trên là 10 ví dụ cho các cách sử dụng ký hiệu hoặc toán tử mà bạn có thể thử, hãy vận dụng chúng vào học tập và công việc để hệ điều hành Linux không còn là nỗi ám ảnh nữa.