8 Ví dụ thực tế về lệnh Xargs của Linux dành cho người mới bắt đầu

theanh

Administrator
Nhân viên
Lệnh Linux xargs có thể không phải là một công cụ dòng lệnh phổ biến, nhưng điều đó không thay đổi được sự thật rằng nó cực kỳ hữu ích, đặc biệt là khi kết hợp với các lệnh khác như find và grep. Nếu bạn chưa biết xargs và muốn hiểu cách sử dụng của nó, bạn sẽ vui mừng khi biết rằng chúng tôi sẽ làm điều đó ở đây.
Mã:
Trước khi tiếp tục, hãy nhớ rằng tất cả các ví dụ được trình bày trong hướng dẫn này đã được thử nghiệm trên Ubuntu 22.04 LTS. Shell được sử dụng trên hệ thống của tôi là Bash.

1. Lệnh Xargs hoạt động như thế nào?​

Vâng, trước khi tìm hiểu cách sử dụng, điều quan trọng là phải hiểu chính xác Xargs thực hiện những gì. Nói một cách dễ hiểu, công cụ này - ở dạng cơ bản nhất - đọc dữ liệu từ đầu vào chuẩn (stdin) và thực thi lệnh (được cung cấp cho nó dưới dạng đối số) một hoặc nhiều lần dựa trên dữ liệu đầu vào đã đọc. Bất kỳ khoảng trắng và khoảng cách nào trong đầu vào đều được coi là dấu phân cách, trong khi các dòng trống sẽ bị bỏ qua.

Nếu không có lệnh nào được cung cấp dưới dạng đối số cho xargs, lệnh mặc định mà công cụ thực thi là echo. Ví dụ, trong ví dụ sau, tôi vừa thực thi 'xargs' và nhập 'Hello World' trên stdin. Khi tôi nhấn Ctrl+D (để báo cho xargs biết rằng chúng ta đã hoàn tất việc nhập dữ liệu), lệnh echo được thực thi tự động và 'Hello World' được in lại.


2. Làm thế nào để sử dụng xargs với lệnh khác?​

Mặc dù echo là lệnh mặc định mà xargs thực thi, bạn có thể chỉ định rõ ràng bất kỳ lệnh nào khác. Ví dụ, bạn có thể truyền lệnh find cùng với tùy chọn '-name' của nó làm đối số cho xargs, sau đó truyền tên tệp (hoặc loại tệp) mà bạn muốn tìm để tìm kiếm làm đầu vào thông qua stdin.

Sau đây là câu hỏi đầy đủ về lệnh:
Mã:
xargs find -name
Ví dụ, chúng tôi đã cung cấp "*.txt" làm đầu vào thông qua stdin, điều này có nghĩa là chúng tôi muốn lệnh find tìm kiếm tất cả các tệp .txt trong thư mục hiện tại (cũng như các thư mục con của nó).

Sau đây là lệnh đang hoạt động:


3. Cách thực hiện lệnh xargs nhiều lần (mỗi lần cho mỗi dòng/đối số đầu vào)​

Trong ví dụ chúng ta đã thảo luận ở phần trước, chúng ta muốn tìm kiếm các tệp .txt, vì vậy chúng ta đã cung cấp "*.txt" trong đầu vào. Nhưng nếu yêu cầu là cũng tìm kiếm các loại tệp khác, như .log và .tmp thì sao?

Hãy thử cung cấp những tệp này làm đầu vào cho xargs sau "*.txt" và xem điều gì xảy ra. Vâng, bạn sẽ nhận được lỗi tương tự như sau:



Đó là vì xargs truyền "*.txt" và "*.log" làm đầu vào tên tệp cho lệnh find và sau đó find không thành công vì lệnh này chạy với hai tên tệp trong đầu vào. Bạn có thể nghĩ về lệnh find chạy theo cách sau:
Mã:
find -name "*.txt" "*.log"
Và đó không phải là cách đúng.

Điều chúng ta muốn là lệnh xargs trước tiên phải truyền "*.txt" cho lệnh find, để find cung cấp cho chúng ta kết quả liên quan đến các tệp .txt, sau đó truyền "*.log". Điều này có thể thực hiện được bằng cách sử dụng tùy chọn dòng lệnh -L mà xargs cung cấp.

Tùy chọn dòng lệnh -L yêu cầu một số mà nó coi là số lượng tối đa các dòng không trống cần được truyền làm đầu vào cho lệnh trong một lần. Vì vậy, trong trường hợp của chúng ta, giá trị đó sẽ là 1, vì chúng ta muốn một dòng đầu vào được truyền làm đầu vào cho find tại một thời điểm.

Vì vậy, đây là lệnh mà chúng ta nên chạy:
Mã:
xargs -L 1 find -name
Ảnh chụp màn hình sau đây cho thấy lệnh đã đề cập ở trên đang hoạt động:



Cho đến nay, mọi thứ vẫn ổn. Nhưng nếu bạn truyền dữ liệu đầu vào theo cách sau thì sao:
Mã:
"*.txt" "*.log"
Vâng, lệnh sẽ không thành công vì '-L 1' sẽ đảm bảo rằng toàn bộ dòng được truyền đến lệnh find.



Trong những tình huống như thế này, bạn có thể sử dụng tùy chọn dòng lệnh '-n'.

Tùy chọn dòng lệnh '-n', giống như '-L', yêu cầu một số biểu thị số đối số mà bạn muốn xargs truyền qua mỗi dòng lệnh. Trong trường hợp chúng ta vừa thảo luận, "*.txt" và "*.log" phải là các đối số khác nhau và vì chúng ta muốn chúng được truyền riêng lẻ nên chúng ta sẽ phải cung cấp '1' làm giá trị cho '-n'.

xargs -n 1 find -name



Vì vậy, đây là những cách chúng ta có thể khiến xargs thực thi một lệnh nhiều lần.

4. Cách khiến xargs xử lý tên tệp có khoảng trắng​

Nếu bạn nhớ lại, lúc đầu chúng tôi đã đề cập rằng xargs coi khoảng trắng (cũng như ký tự xuống dòng) là dấu phân cách. Điều này có thể gây ra sự cố trong trường hợp tên tệp được truyền làm đầu vào cho xargs chứa khoảng trắng.

Ví dụ, giả sử thư mục hiện tại chứa tệp có tên 'newmusic.mp3' và bạn muốn xargs truyền tên này cho mplayerđể mplayer có thể phát tệp. Nếu bạn làm theo cách thông thường, bạn sẽ gặp lỗi:



Đó là vì do khoảng trắng giữa 'new' và 'music.mp3', nên mplayer coi chúng là hai tệp khác nhau. Một cách để giải quyết vấn đề này là sử dụng dấu gạch chéo ngược khi cung cấp đầu vào:
Mã:
new\ music.mp3
Cách khác là thay đổi dấu phân cách, bạn có thể thực hiện bằng tùy chọn -d. Ví dụ, bạn có thể yêu cầu xargs chỉ coi newline là một dấu phân cách, điều này có thể được thực hiện theo cách sau:
Mã:
xargs -d '\n' mplayer

5. Làm thế nào để xargs xử lý tên tệp có ký tự newline​

Vậy là chúng ta đã biết cách làm cho xargs xử lý tên tệp có chứa khoảng trắng. Nhưng còn newline thì sao? Đúng vậy, tên tệp cũng có thể có ký tự newline. Ví dụ, có một tệp có tên là 'foo'[newline]'file.txt'. Trên thiết bị đầu cuối, tên được hiển thị là 'foo?file.txt'.



Bây giờ, giả sử, tôi muốn lệnh find tìm tất cả các tệp có tên bắt đầu bằng văn bản 'foo', sau đó sử dụng xargs để mở các tệp này trong gedit. Đây là lệnh:
Mã:
find . -name "foo*" | xargs gedit
Thật đáng buồn, lệnh không đạt được mục đích của nó khi một tệp mới có tên 'foo' mở trong Gedit. Có thể là do ký tự xuống dòng được xargs coi là dấu phân cách.

Để giải quyết vấn đề này, hãy sử dụng tùy chọn -print0 mà find cung cấp và kết hợp với tùy chọn -0 của xarg. Đây là cách trang hướng dẫn của find giải thích tùy chọn này:
Mã:
[B] -print0[/b]
Đúng; in tên tệp đầy đủ trên đầu ra chuẩn, theo sau là ký tự null (thay vì ký tự xuống dòng mà -print sử dụng). Điều này cho phép các tên tệp chứa dòng mới hoặc các loại khoảng trắng khác được các chương trình xử lý đầu ra tìm hiểu chính xác. Tùy chọn này tương ứng với tùy chọn -0 của xargs.
Vì vậy, đây là lệnh chúng ta nên sử dụng:
Mã:
find . -name "foo*" -print0 | xargs -0 gedit

6. Cách tìm tệp chứa văn bản cụ thể​

Lệnh xargs thực sự hữu ích nếu bạn muốn tìm kiếm tệp chứa văn bản/chuỗi cụ thể. Ví dụ: nếu bạn muốn tìm tệp .txt chứa văn bản 'abc', thì có thể thực hiện theo cách sau:
Mã:
find -name "*.txt" | xargs grep "abc"
Đây là lệnh đang hoạt động:



Như khá rõ ràng, trong trường hợp này, lệnh xargs nhận đầu vào từ lệnh find.

7. Cách để xargs chấp nhận đầu vào từ một tệp​

Cho đến nay, chúng ta đã thấy xargs chấp nhận đầu vào từ stdin (là hành vi mặc định) cũng như từ một lệnh khác (đã thảo luận trong phần trước). Tuy nhiên, nếu muốn, bạn cũng có thể để xargs chấp nhận đầu vào từ một tệp.

Tùy chọn -a của lệnh cho phép bạn thực hiện việc này. Tùy chọn này mong đợi một tên tệp - đây sẽ là tệp mà xargs sẽ đọc đầu vào.

Ví dụ, giả sử có một tệp có tên 'input.txt'. Nó chứa dữ liệu đầu vào cho xargs (về cơ bản, nội dung là hai tên tệp: testfile1.txt và testfile2.txt). Sau đây là cách xargs có thể được sử dụng để đọc dữ liệu đầu vào từ tệp này và chuyển nó cho một lệnh khác, chẳng hạn như ls.
Mã:
xargs -a input.txt ls -lart
Sau đây là lệnh đang hoạt động:


8. Làm thế nào để xargs tìm kiếm sự cho phép của người dùng trước khi thực hiện lệnh​

Chúng tôi đã thảo luận về cách bạn có thể làm cho xargs thực hiện một lệnh nhiều lần (xem điểm 3 ở trên). Nhưng nếu bạn muốn xargs xin phép bạn mỗi khi nó chạy lệnh thì sao? Điều này có thể không? Có, đúng vậy - tùy chọn dòng lệnh -p giúp thực hiện được điều đó.

Sau đây là ví dụ về cách bạn có thể chạy xargs ở chế độ tương tác:



Chúng ta chỉ mới bắt đầu tìm hiểu ở đây vì có rất nhiều tính năng khác mà lệnh xargs cung cấp dưới dạng tùy chọn dòng lệnh. Hãy thử các khái niệm/tính năng xargs mà chúng tôi đã giải thích trong hướng dẫn này và trong trường hợp có bất kỳ nghi ngờ hoặc thắc mắc nào, hãy xem qua trang hướng dẫn của nó.
 
Back
Bên trên