bash - {} có nghĩa là gì?


1

Tôi muốn xóa các tập tin có kích thước = 0. Vì vậy, tôi đã thử:

find ./ -size 0 | xargs rm

Nhưng nó có một vấn đề với các tập tin, tên bắt đầu bằng không gian. Tôi đã tìm thấy cái này:

find ./ -size 0 -exec rm -i {} \;

Nó hoạt động. Tôi nghĩ rằng cách của tôi với xargslà quá tinh vi cho việc này.

{} \;nghĩa là gì?

Bạn có thể giải thích cho tôi? Tiếng Anh của tôi không tốt lắm, vì vậy hãy viết đơn giản.



1
Nhân tiện: Có -print0trong tìm và -0trong xargs. Sử dụng chúng là rất bắt buộc khi làm những thứ như thế này. Bởi vì nếu nó tìm thấy "/ bla" ...
Daniel B

@DanielB -print0xargs -0đều không chuẩn và thường vô dụng, findmột mình có thể đạt được cùng một mục tiêu mà không cần những hack này.
jlliagre

Câu trả lời:


6

{}hoàn toàn không có ý nghĩa gì bash, vì vậy được thông qua không được sửa đổi như là một đối số cho lệnh được thực thi ở đây find.

Mặt khác, ;có một ý nghĩa cụ thể bash. Nó thường được sử dụng để phân tách các lệnh tuần tự khi chúng nằm trên cùng một dòng lệnh. Ở đây, dấu gạch chéo ngược \;được sử dụng chính xác để ngăn dấu chấm phẩy được hiểu là dấu phân cách lệnh bashvà sau đó cho phép nó được truyền dưới dạng tham số cho lệnh bên dưới , find. Trích dẫn dấu chấm phẩy, tức là ";"hoặc ';', có thể là một cách thay thế để nó không bị xử lý.

Lệnh:

find ./ -size 0 -exec rm -i {} \;

có nghĩa là: tìm trong thư mục hiện tại (lưu ý rằng không /có ích ở đây, .dù sao cũng không thể là thư mục) bất cứ thứ gì có kích thước bằng 0 và cho mỗi đối tượng được tìm thấy, hãy chạy lệnh rm -i name, tức là nhắc nhở tương tác cho mỗi tệp nếu bạn muốn xóa nó {}được thay thế bởi mỗi tên tệp được tìm thấy trong lệnh thực thi. Một tính năng hay là tên tệp này hoàn toàn là một đối số, bất kể tên tệp là gì (thậm chí có chứa các khoảng trắng được nhúng, tab, nguồn cấp dữ liệu và bất kỳ ký tự nào). Đây không phải là trường hợp xargs, trừ khi sử dụng hack không di động. Cuối cùng ;là ở đó để kết thúc -execđiều khoản. Lý do tại sao phần cuối của nó cần được phân định là các findmệnh đề khác có thể tuân theo điều khoản này -exec, mặc dù điều này hiếm khi được thực hiện.

Một vấn đề với lệnh này là nó sẽ không bỏ qua các tệp không đơn giản, do đó có thể nhắc người dùng xóa ổ cắm, khối và thiết bị ký tự, đường ống và thư mục. Nó sẽ luôn luôn thất bại với cái sau ngay cả khi bạn trả lời có.

Một vấn đề khác, mặc dù không thực sự quan trọng ở đây, đó là rmsẽ được gọi cho mỗi tệp có kích thước bằng không. Nếu bạn thay thế -execkết thúc từ /;đến +, findsẽ tối ưu hóa việc tạo quy trình phụ bằng cách chỉ gọi rmsố lần tối thiểu có thể, thường chỉ một lần.

Đây là cách tôi sẽ sửa đổi lệnh này:

find . -type f -size 0 -exec rm -i {} +


1
@ The_IT_Guy_You_D Don't_Like Không phải vậy. Chính xác hơn, thay thế tham số yêu cầu một $ký tự trước {và yêu cầu ít nhất một tên biến có mặt giữa các dấu ngoặc nhọn. {}một mình không có ý nghĩa cho vỏ và được giữ nguyên bởi nó.
jlliagre

Tại sao điều này không hoạt động mà không có +? Nó đang làm gì ở đây vậy?
CGTheLegend

1
@CGTheLegend Nó không hoạt động mà không có +-execbiểu thức có số lượng đối số thay đổi nên cần được chấm dứt bởi một cái gì đó để được phân tích cú pháp chính xác và các biểu thức tiếp theo được tìm thấy chính xác. Kẻ hủy diệt có thể là +hoặc ;.
jlliagre

3

Khi sử dụng find -exec, {}được mở rộng đến từng kết quả được tìm thấy.

Ví dụ, nếu bạn có một thư mục examplechứa 3 file a.txt, b.txtc.txt, find example/ -exec rm -i {} \;sẽ mở rộng để:

find example/ -exec rm -i example/a.txt \;
find example/ -exec rm -i example/b.txt \;
find example/ -exec rm -i example/c.txt \;

\;cuối là đơn giản một ;lối thoát để chỉ ra sự kết thúc của mẫu exec. Nếu không, nó sẽ được giải thích bằng chính vỏ.


2
Lệnh sẽ không thực sự mở rộng thành ba lệnh bạn đã viết, điều này sẽ dẫn đến nhiều lời nhắc cho cùng một tệp và dẫn đến lỗi "không tìm thấy tệp" nếu bạn chấp nhận xóa chúng, nhưng chỉ đơn giản là:rm -i "example/a.txt" ; rm -i "example/b.txt" ; rm -i "example/c.txt"
jlliagre

0

Kết hợp với tùy chọn findcủa lệnh exec, {}phần được thay thế bằng tên của các tệp được tìm thấy khi lệnh được thực thi. Điều \;này cũng quan trọng, bởi vì đó là những gì xác định kết thúc của lệnh đang được thực thi

Ví dụ

find ~ -name \*.bak -exec -rm -f {} \;

sẽ xóa tất cả các tệp kết thúc ở .bakbất kỳ đâu trong thư mục chính của người dùng hoặc trong các thư mục chứa trong đó. Bằng cách thực hiện rm -ftrên mỗi tập tin được tìm thấy.

xargs lấy các dòng đầu vào tiêu chuẩn, thường là từ một đường ống và tạo thành phần đuôi của các đối số từ nó khi nó thực thi lệnh bạn đưa ra


0

Để lần lượt từng trường hợp: -

xargs

Có gì chương trình này không có gì để thêm mỗi dòng từ đầu vào như một tham số để bất cứ điều gì lệnh được thông qua như là tham số của riêng mình, sau đó chạy lệnh kết quả, vì vậy nếu finddanh sách ba tập tin a, bctrong thư mục hiện nó sẽ cung cấp cho như đầu ra:

./a
./b
./c

Nếu điều này được dẫn đến xargs rm, thì lệnh này sẽ được thực thi:

rm ./a ./b ./c

Tuy nhiên, nếu findcũng tìm thấy một tệp được gọi " d e ", thì lệnh được thực hiện sẽ trở thành:

rm ./a ./b ./c ./ d e 

Để xử lý điều này, findcung cấp một tùy chọn -print0, thêm ký tự null ( \0) sau mỗi tệp, thay vì dòng mới thông thường. Để biết xargsrằng đầu vào ở dạng này, hãy thêm tham số -0, vì vậy lệnh:

find . ... -print0|xargs -0 rm

sẽ xây dựng và thực thi lệnh:

rm "./a" "./b" ."/c" "./ d e "

Điều này sẽ hoạt động trên tất cả các tên tệp, bao gồm cả tên chứa khoảng trống, tab và dòng mới.

find -exec

Khi tùy chọn này được gọi, thì những gì tiếp theo (tối đa \;) được thực thi cho mỗi tệp được tìm thấy. Điều này không thực sự hữu ích trừ khi có một số phương tiện để tham khảo tệp hiện được tìm thấy và đó là những gì {}. Nó có thể được gọi nhiều lần trong chuỗi chạy, ví dụ: sao chép một lựa chọn các tệp vào thư mục sao lưu:

find . ... -exec cp "{}" "/BackUp/{}" \;

Điều này trong findví dụ trên sẽ lần lượt thực thi:

cp "./a" "/BackUp/./a"
cp "./b" "/BackUp/./b"
cp "./c" "/BackUp/./c"

Lưu ý rằng, bên ngoài việc sử dụng chúng trong findlệnh {}có ý nghĩa đặc biệt trong bash (nhiều lệnh và danh sách mở rộng), nhưng chúng liên quan đến các ký tự khác giữa các dấu ngoặc: chuỗi {}được sao chép theo nghĩa đen, do đó không cần thoát.

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.