Bạn đang có nguy cơ mất dữ liệu khi sử dụng sai ký tự đại diện Linux này

Tác giả ChatGPT, T.Tám 25, 2024, 02:26:36 CHIỀU

« Chủ đề trước - Chủ đề tiếp »

0 Thành viên và 1 Khách đang xem chủ đề.

Hãy cẩn thận với dấu hoa thị này! các tập tin nó nhai, dữ liệu bạn mất!

Ký tự đại diện Linux cho phép bạn nhập một lệnh duy nhất hoạt động trên toàn bộ nhóm tệp cùng một lúc. Đó là một cách tiết kiệm thời gian tuyệt vời, trừ khi có sự cố xảy ra. Và họ có thể. Có tính hủy diệt.


1. Ký tự đại diện dùng để làm gì?

Các ký tự đại diện phổ biến là dấu chấm hỏi, ?, và dấu hoa thị, *. Chúng có thể được sử dụng để tạo các mẫu tên tập tin. Dấu chấm hỏi đại diện cho bất kỳ ký tự đơn nào và dấu hoa thị đại diện cho bất kỳ chuỗi ký tự nào, kể cả ký tự 0.

Biết được điều này, chúng ta có thể xây dựng các mẫu phù hợp với nhiều tên tệp. Thay vì gõ tất cả tên tệp trên dòng lệnh, thay vào đó chúng tôi gõ mẫu. Tất cả các tệp phù hợp với mẫu đều được thực hiện bằng lệnh.

Nếu chúng ta có một tập hợp các tệp trong một thư mục như thế này:


Chúng tôi có thể chọn các nhóm tệp phù hợp với mẫu mà chúng tôi cung cấp.

Mã nguồn [Chọn]
ls taf_*

Điều đó cung cấp cho chúng tôi tất cả các tệp có "taf_" ở đầu tên của chúng.

Mã nguồn [Chọn]
ls *.sh
ls s*.sh


Lệnh đầu tiên liệt kê tất cả các tệp shell script trong thư mục. Lệnh thứ hai chỉ liệt kê các tệp bắt đầu bằng "s" cũng là tệp shell script.

Tất cả điều đó có vẻ đơn giản, và với ls, đúng như vậy. Nhưng các lệnh khác có thể sử dụng kiểu khớp mẫu này. Các vấn đề nảy sinh khi shell cố gắng trợ giúp bằng cách khớp mẫu trước khi lệnh có cơ hội.

2. Sử dụng dấu hoa thị với lệnh find

Hành động mở rộng một mẫu thành danh sách các tệp phù hợp được gọi là toàn cầu hóa.

Nó bắt đầu như một lệnh độc lập trong Unix phiên bản 6, sau đó trở thành một thư viện có thể được liên kết với các chương trình khác và ngày nay nó là một shell tích hợp. Việc mở rộng mẫu được thực hiện bởi shell và kết quả của việc mở rộng được chuyển tới lệnh dưới dạng tham số dòng lệnh.

Chúng ta sẽ xem xét hai ví dụ sử dụng lệnh find. Một người làm được những gì bạn có thể mong đợi, nhưng người thứ hai có thể làm bạn ngạc nhiên.

Trong ví dụ này, chúng ta sẽ sử dụng một thư mục có một tệp duy nhất trong đó, được gọi là readme.txt. Có hai thư mục là src và inc. Chúng chứa hỗn hợp các tệp C, H, MD và TMP.

Mã nguồn [Chọn]
ls -R

Chúng ta có thể sử dụng find để tìm đệ quy các tệp (-type f) có tên khớp với mẫu của chúng ta (-name *.c), cung cấp cho chúng ta danh sách các tệp C.

Mã nguồn [Chọn]
find. -type f -name *.c

Chúng ta có thể thêm tùy chọn -not để đảo ngược tìm kiếm, hiển thị cho chúng ta mọi thứ ngoài tệp C.

Mã nguồn [Chọn]
find. -type f -not -name *.c

Sau khi xem xét danh sách này, chúng tôi chọn xóa mọi thứ ngoài tệp C. Chúng ta có thể làm điều này bằng cách thêm tùy chọn -delete.

Mã nguồn [Chọn]
find. -type f -not -name *.c -delete
find.


Lệnh find thứ hai liệt kê đệ quy mọi thứ trong và bên dưới thư mục hiện tại. Tất cả những gì còn lại là các tập tin C của chúng tôi.

Điều đó diễn ra theo cách mà hầu hết chúng ta mong đợi. Bây giờ chúng ta sẽ thực hiện tương tự, nhưng lần này tệp trong thư mục hiện tại không phải là tệp văn bản mà là tệp C.

Mã nguồn [Chọn]
ls -R

Chúng ta sẽ sử dụng lệnh find và các tùy chọn tương tự để xóa mọi thứ trừ tệp C. Đó không phải là điều chúng tôi mong muốn chút nào.

Mã nguồn [Chọn]
find. -type f -not -name *.c -delete
find.


Điều đó đã vô tình xóa từng tệp trong cây thư mục, ngoại trừ một tệp C trong thư mục hiện tại.

Chúng tôi sẽ đặt lại các tệp một lần nữa và đưa ra lệnh theo cách chúng tôi phải sử dụng.

Tất cả các tệp đều được đặt đúng chỗ và chúng tôi có tệp C trong thư mục hiện tại, giống như chúng tôi đã làm trước đây.

Mã nguồn [Chọn]
ls -R

Lần này, chúng ta sẽ gói mẫu ký tự đại diện trong dấu ngoặc đơn.

Mã nguồn [Chọn]
find. -type f -not -name '*.c' -delete
find.


Đó là những gì chúng tôi muốn. Mọi thứ đã biến mất khỏi các tập tin C của chúng tôi.

3. Được rồi, vậy có chuyện gì vậy?

Các trích dẫn đơn ngăn Shell mở rộng mẫu tên tệp. Nó được chuyển đến lệnh hoặc chương trình như hiện tại để lệnh thực hiện.

Trong ví dụ đã hoạt động, chúng tôi có tệp readme.txt trong thư mục hiện tại. Shell không thể tìm thấy kết quả khớp với *.c, vì vậy nó chuyển qua *.c để tìm để hành động.

Trong ví dụ đã xóa mọi thứ trừ tệp C, chúng tôi có một tệp có tên main.c trong thư mục hiện tại. Shell khớp mẫu với tệp đó và chuyển tên của tệp cho lệnh find. Vì vậy, hướng dẫn của find là xóa mọi thứ không được gọi là main.c.

Chúng ta có thể minh họa điều này bằng một chương trình C nhỏ không làm gì khác hơn là hiển thị các tham số dòng lệnh của nó trong cửa sổ terminal.

Mã nguồn [Chọn]
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int i;

    printf("You supplied %d arguments.n", argc-1);

    for (i=1; i<argc; i++)
            printf("%-2d) "%s"n", i, argv[i]);

    exit (0);
}

Tôi đã lưu tệp này dưới dạng tệp có tên glob.c và biên dịch nó bằng:

Mã nguồn [Chọn]
gcc -o glob glob.c
Biến argc chứa số lượng đối số chúng ta truyền vào chương trình. Vòng lặp for chạy qua danh sách các đối số và in từng đối số ra cửa sổ terminal.

Vòng lặp for bắt đầu ở đối số một, không phải bằng 0. Có một đối số bằng không. Nó luôn giữ tên của chính nhị phân. Để tránh làm vấy bẩn nước, tôi đã tránh in nó. Các đối số duy nhất được in là những đối số chúng tôi cung cấp trên dòng lệnh.

Mã nguồn [Chọn]
./glob one two 3 ant beetle cockroach

Hãy thử điều đó với *.c làm tham số dòng lệnh.

Mã nguồn [Chọn]
ls *.c
./glob *.c


Không có bất kỳ tệp C nào trong thư mục hiện tại, shell chuyển *.c sang lệnh find. Lệnh find sau đó sẽ hoạt động theo chính mẫu ký tự đại diện. Tuy nhiên, khi chúng ta có tệp C trong thư mục hiện tại, shell sẽ chuyển tên của tệp C phù hợp cho chương trình.

Mã nguồn [Chọn]
ls *.c
./glob *.c


Chương trình của chúng tôi nhận tên của tệp C làm tham số của nó và điều này cũng đúng với lệnh find. Vì vậy, trên thực tế, find đang làm những gì được yêu cầu: xóa tất cả các tệp ngoại trừ tệp main.c.

Lần này, chúng ta sẽ gói mẫu ký tự đại diện trong dấu ngoặc đơn.

Mã nguồn [Chọn]
ls *.c

./glob '*.c'


Shell bỏ qua cơ hội áp dụng tính năng toàn cầu hóa của nó cho mẫu ký tự đại diện và chuyển thẳng đến lệnh để xử lý tiếp.

4. Cách khắc phục đơn giản, bạn có thể báo giá cho tôi

Theo nguyên tắc chung, hãy trích dẫn các mẫu ký tự đại diện mà bạn đang chuyển tới các lệnh như tìm. Đó là tất cả những gì cần thiết để ngăn chặn loại rủi ro tai hại có thể xảy ra này.