Hiểu tùy chọn -exec của find (1) (dấu ngoặc nhọn & dấu cộng)


17

Sử dụng lệnh sau đây, ai đó có thể vui lòng giải thích chính xác mục đích cho dấu ngoặc nhọn kết thúc ({}) và dấu cộng (+) là gì không?

Và làm thế nào để lệnh hoạt động khác nhau nếu chúng bị loại khỏi lệnh?

find . -type d -exec chmod 775 {} +

Câu trả lời:


19

Các dấu ngoặc nhọn sẽ được thay thế bằng kết quả của findlệnh và chmodsẽ được chạy trên mỗi hàm. Các +làm cho findcố gắng chạy càng ít lệnh càng tốt (như vậy, chmod 775 file1 file2 file3như trái ngược với chmod 755 file1, chmod 755 file2, chmod 755 file3). Không có chúng, lệnh sẽ chỉ báo lỗi. Tất cả điều này được giải thích trong man find:

-exec command ;

      Thực thi lệnh ; đúng nếu trạng thái 0 được trả về. Tất cả các đối số sau đây sẽ findđược coi là đối số cho lệnh cho đến khi ;gặp phải đối số bao gồm ' '. Chuỗi ' {}' được thay thế bằng tên tệp hiện tại đang được xử lý ở mọi nơi nó xuất hiện trong các đối số của lệnh, không chỉ trong các đối số chỉ có một mình, như trong một số phiên bản find. Giáo dục

-exec command {} +

      Biến thể -exechành động này chạy lệnh được chỉ định trên các tệp đã chọn, nhưng dòng lệnh được tạo bằng cách nối thêm từng tên tệp đã chọn ở cuối; tổng số lệnh gọi của lệnh sẽ ít hơn nhiều so với số lượng tệp được khớp. Giáo dục


12

Ngoài câu trả lời của terdon,

  • Rõ ràng là -exec …phải chấm dứt với một dấu chấm phẩy ( ;) hoặc dấu cộng ( +). Dấu chấm phẩy là một nhân vật đặc biệt trong vỏ (hoặc, ít nhất, mỗi shell Tôi đã từng sử dụng), do đó, nếu nó được sử dụng như một phần của findlệnh , nó phải được thoát ra hoặc trích dẫn ( \;, ";"hoặc ';').
  • Với -exec … ;, {}chuỗi có thể xuất hiện bất kỳ số lần nào trong lệnh, bao gồm 0 hoặc hai hoặc nhiều hơn, ở bất kỳ vị trí nào.  Xem điều này để biết ví dụ về lý do tại sao bạn có thể muốn làm -execmà không sử dụng {}.   Có hai hoặc nhiều lần xuất hiện là hữu ích chủ yếu bởi vì, trong (ít nhất) một số phiên bản của find, {}không cần phải là một từ; nó có thể có các nhân vật khác ở đầu hoặc cuối; ví dụ,

    find . -type f -exec mv {} {}.bak ";"
    

    Với -exec … +, {}chuỗi phải xuất hiện như là đối số cuối cùng trước +. Một lệnh như

    find . -name "*.bak" -exec mv {} backup_folder +
    

    kết quả trong find: missing argument to ‘-exec’thông báo lỗi bí ẩn .

    • Một cách giải quyết cho điều này đặc trưng cho các lệnh cpmv

      find . -name "*.bak" -exec mv -t backup_folder {} +
      

      hoặc là

      find . -name "*.bak" -exec mv --target-directory=backup_folder {} +
      

    Các {}phải là một từ bằng cách riêng của mình; nó không thể có các ký tự khác ở đầu hoặc cuối. Và, trong (ít nhất) một số phiên bản find, bạn có thể không có nhiều hơn một {}.

  • Một lưu ý tỉnh táo: Bạn có thể nói

    tìm thấy . -name "* .sh" -type f -executable -exec {} tùy chọn đối số ở đây ";"

    để chạy từng tập lệnh của bạn. Nhưng

    tìm thấy . -name "* .sh" -type f -executable -exec {} +

    chạy một trong các tập lệnh của bạn, với tên của tất cả các tập lệnh khác làm tham số. Điều này tương tự như nói

    ./*.sh
    

    như một lệnh shell, ngoại trừ findkhông đảm bảo rằng nó sắp xếp kết quả của nó, vì vậy bạn không được đảm bảo chạy aaa.sh ( *.shtệp đầu tiên theo thứ tự bảng chữ cái của bạn ) như khi bạn chạy ./*.sh.

  • Một khía cạnh của findđiều đó có thể không hoàn toàn rõ ràng đối với người mới bắt đầu là dòng lệnh, một cách hiệu quả, là một câu lệnh thực thi trong một ngôn ngữ phức tạp. Ví dụ,

    find . -name "*.sh" -type f -executable -print
    

    có nghĩa

    for each file
        if the file’s name matches `*.sh` (i.e., if it ends with `.sh`)
        then
            if it is a plain file (i.e., not a directory)
            then
                if it is executable (i.e., the appropriate `---x--x--x` bit is set)
                then
                    print the file’s name
                end if
            end if
        end if
    end loop
    

    hoặc đơn giản,

    for each file
        if the file’s name matches `*.sh`  AND  it is a plain file  AND  it is executable
        then
            print the file’s name
        end if
    end loop
    

    Một số -từ khóa là cả một hành động thực thi và kiểm tra. Đặc biệt, điều này đúng cho -exec … ;; ví dụ,

    find . -type f -exec grep -q cat {} ";" -print
    

    Dịch sang

    cho mỗi tập tin
        nếu nó là một tập tin đơn giản (nghĩa là không phải là một thư mục)
        sau đó
            thực hiện tên tập tin mèo grep -q
            nếu quá trình thành công (nghĩa là thoát với trạng thái 0)
            sau đó
                in tên tập tin
            kết thúc nếu
        kết thúc nếu
    kết thúc vòng lặp

    mà sẽ in tên của tất cả các file có chứa chuỗi “ cat”. Và, trong khi đây là điều grepcó thể tự làm (với tùy chọn -l(chữ thường L)), có thể hữu ích khi sử dụng nó findđể tìm các tệp có chứa một chuỗi nhất định VÀ có kích thước nhất định VÀ được sở hữu bởi một chủ sở hữu nhất định VÀ đã được sửa đổi trong một phạm vi thời gian nhất định, Hoài.

    Tuy nhiên, điều này không làm việc cho -exec … +. Vì -exec … +thực thi một lệnh cho nhiều tệp, không có nghĩa gì khi sử dụng nó làm điều kiện logic bên trong một for each file …vòng lặp.

  • Mặt trái của ở trên là findthường thoát với trạng thái thoát là 0 trừ khi bạn đưa ra các đối số không hợp lệ hoặc nó gặp một thư mục mà nó không thể đọc được. Ngay cả khi một chương trình mà bạn thực thi không thành công (thoát với trạng thái thoát khác không), findsẽ thoát với trạng thái thoát là 0.  Ngoại trừ  nếu một chương trình mà bạn thực hiện -exec … +không thành công (thoát với trạng thái thoát khác không), findsẽ thoát với trạng thái thoát không bằng không.

Ngoài một triệu phiên bản find(1) và thử nghiệm những gì findthực sự có trên một vài hệ thống, Phiên bản Thông số kỹ thuật cơ sở nhóm mở số 7, 2013 Edition cung cấp một số thông tin về những gì findphải, có thể và không được làm.


3
Coi chừng rằng ví dụ của bạn sử dụng ... -exec mv {} {}.bak ...không được đảm bảo để hoạt động như mong đợi với tất cả các findtriển khai. Các trạng thái tiêu chuẩn POSIX {}phải xuất hiện một mình để luôn được nhận dạng, nếu không, hành vi được tự do giữ các ký tự không thay đổi hoặc thay thế chúng bằng tên đường dẫn. Trong trường hợp trước, toàn bộ lệnh của bạn về cơ bản sẽ xóa tất cả các tệp nhưng lệnh cuối cùng được tìm thấy ...
jlliagre
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.