Sự khác biệt giữa '{}' và {} trong lệnh find?


18

Trong tài liệu , tôi thấy cách sử dụng cả hai cách:

find . -type f -exec file '{}' \;

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \

4
Chắc chắn có vẻ như nó không liên quan gì đến lệnh find, lệnh và thay vào đó phải thực hiện với trích dẫn thích hợp cho lệnh được gọi.
Zoredache

1
Hãy thử nó với cá, thay vì bash.
Charles Duffy

Câu trả lời:


24

Đối với bashvỏ, '{}'{}có thể thay thế cho nhau. Đây không phải là trường hợp với tất cả các shell (chẳng hạn như fish).

Đặt đối số trong dấu ngoặc đơn cho biết rõ ràng rằng dấu ngoặc nhọn sẽ được gửi đến find. Tùy thuộc vào cách sử dụng, vỏ bash đôi khi thay thế nội dung của dấu ngoặc nhọn.

Như được thấy dưới đây, bash không thay thế dấu ngoặc rỗng và chúng được truyền vào lệnh. Đối với findlệnh, nó không thành vấn đề.

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

$ echo '{1,3}'
{1,3}

4
Không quan trọng với bash. Có vấn đề với cá.
Charles Duffy

1
Tôi sẽ thay thế " are interchangeable"bằng " are interchangeable in some shells, not in all of them. ALWAYS use the single quotes to make sure they get passed as-is to the find command"(thói quen tốt bắt đầu bằng cách đảm bảo bạn sử dụng đúng cách ngay cả khi bạn tình cờ (luôn luôn?) Ở trên một hệ thống cho phép người mơ hồ)
Olivier Dulac

9

Với hầu hết tất cả các trình thông dịch shell có sẵn, hoàn toàn không có sự khác biệt giữa '{}'{}.

Các trích dẫn đơn thường được sử dụng để bảo vệ chuỗi nhúng khỏi bị thay thế bởi một thứ khác, ví dụ:

  • 'a b' là một tham số ba ký tự đơn, không có dấu ngoặc kép sẽ là hai tham số ký tự đơn
  • '$b' nghĩa đen là ký hiệu đô la theo sau chữ b, không có trích dẫn sẽ là bất cứ thứ gì mà biến b chứa và có thể không có gì nếu không đặt
  • '!!' là những dấu chấm than trong khi không được trích dẫn và với một số vỏ tương tác, chúng sẽ mở rộng đến lệnh cuối cùng được đưa vào lịch sử
  • '*' là một dấu hoa thị, không được trích dẫn, nó sẽ được thay thế bằng danh sách tên tệp không bị ẩn trong thư mục hiện tại.

Như không phải là tiêu chuẩn POSIX cũng không phải là vỏ chính ( sh(Bourne), ksh, bash, ash, dash, zsh, csh, tcsh) mở rộng {}đến cái gì khác, có dấu ngoặc kép không bắt buộc.

Tuy nhiên, có một lớp vỏ kỳ lạ, được đặt tên fish, tình cờ mở rộng {}dưới dạng một chuỗi rỗng, ví dụ:

> ps -p %self
  PID TTY          TIME CMD
 5247 pts/1    00:00:00 fish
> echo a {} b '{}'
a  b {}

Đó có lẽ là lý do tại sao findtài liệu GNU đề nghị bảo vệ {}chống lại việc giải thích bằng dấu ngoặc kép hoặc dấu gạch chéo ngược.


9

Đối với hầu hết người dùng (đặc biệt là những người sử dụng vỏ POSIX), không có sự khác biệt.

Theo phần Ví dụ của trang man cho GNU find:

Lưu ý rằng các dấu ngoặc nhọn được đặt trong dấu ngoặc kép để bảo vệ chúng khỏi sự diễn giải như dấu chấm câu shell.

Tôi nghĩ rằng các tác giả của trang người đàn ông GNU đang nhầm lẫn về mặt thận trọng nhưng tôi lưu ý rằng không phải tất cả các ví dụ trong trang người đàn ông của họ đều trích dẫn các dấu ngoặc nhọn. Những ví dụ từ tài liệu tìm kiếm GNU chính thức cũng bỏ qua phần trích dẫn.

Trong các ví dụ từ Đặc tả POSIX / Single UNIX , dấu ngoặc nhọn không được trích dẫn khi được sử dụng với -exectùy chọn.

Với lớp vỏ POSIX, việc mở rộng tham số chỉ xảy ra khi có các tham số đặc biệt được bao quanh trong dấu ngoặc - nhưng không có dấu ngoặc rỗng .

Vỏ Bash bao gồm mở rộng dấu ngoặc như một tính năng (không di động), nhưng các mẫu như vậy chỉ được mở rộng khi dấu phẩy hoặc dấu chấm được bao gồm trong dấu ngoặc nhọn . Bash cũng sử dụng dấu ngoặc nhọn để nhóm lệnh , nhưng điều này không xảy ra trừ khi thực sự một nhóm lệnh trong dấu ngoặc.

Cuối cùng, tôi đã cố gắng chạy find -exec ls -l {} \;trong sh, dashtcshnhưng không ai trong số những vỏ mở rộng {}vào bất cứ điều gì khác. Như những người khác đã chỉ ra, fishvỏ xử lý {}đặc biệt nhưng đây không phải là vỏ POSIX (mà người tạo và người dùng của nó coi là một lợi thế). Không có hại khi trích dẫn niềng răng, nhưng những người đánh máy lười biếng không sử dụng vỏ cá không nên cảm thấy tội lỗi khi bỏ qua chúng.


họ không mắc lỗi, họ đang cố gắng đảm bảo mọi người sử dụng đúng cách (nghĩa là sử dụng '{}'thay vì {}) để vỏ của họ gửi {}đến lệnh find mà không diễn giải nó (như đã đề cập ở trên bởi @ Charles-Duffy, nếu bạn tình cờ sử dụng cá , nó sẽ diễn giải {}nhưng không '{}', vì vậy bạn cần sử dụng cái sau trên vỏ đó (và trên một số cái khác!). Do đó, luôn luôn sử dụng '{}'để tránh bị cắn bởi sự mơ hồ của{}
Olivier Dulac

6

Điều này phụ thuộc vào cú pháp shell của bạn. Khi nghi ngờ, hãy lặp lại nó!

Chạy cái này

echo '{}'

và điều này.

echo {}

Nếu họ tạo ra cùng một đầu ra, thì câu trả lời cho vỏ của bạn là có. Như những người khác đã lưu ý, ít nhất nó sẽ có trong bash và không có trong cá. Đầu ra, là những gì bạn nên tham khảo trang chủ của một lệnh đã cho.


Nếu bạn muốn có được sự tiện dụng, bạn thậm chí có thể thêm tiền tố echovào toàn bộ một dòng lệnh, để xem lệnh thực tế , với tất cả các đối số của nó, rằng shell của bạn sẽ thực sự gọi. Mặc dù vậy, hãy cẩn thận, danh sách bao gồm các lệnh cộng với các đối số là một chuỗi thực sự, mỗi chuỗi có thể trống hoặc có khoảng trắng, nhưng echo in nó một cách mơ hồ như một danh sách được phân tách bằng dấu cách.

Như có thể được xác minh bằng lệnh echo dài dòng hơn một chút (hiển thị các đối số được trích dẫn bằng guillemet),

#!/bin/sh
for a in "$@"; do
    printf '«%s» ' "$a"
done
echo ''

gõ cái này vào dòng lệnh,

find 'My Documents and Settings' -type f -exec file {} \;

có nghĩa là điều này để bash:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»

và điều này ở cá:

«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»

Như một lời khuyên chung, nó không bao giờ đau để trích dẫn.

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.