ในเอกสารฉันเห็นการใช้งานทั้งสองวิธี:
find . -type f -exec file '{}' \;
find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
ในเอกสารฉันเห็นการใช้งานทั้งสองวิธี:
find . -type f -exec file '{}' \;
find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
คำตอบ:
สำหรับbashเปลือก'{}'และ{}สามารถใช้แทนกันได้ นี่ไม่ใช่กรณีที่มีเชลล์ทั้งหมด (เช่นfish)
findใส่อาร์กิวเมนต์ในราคาเดียวอย่างชัดเจนบ่งชี้ว่าวงเล็บปีกกาควรจะส่งไป บางครั้งเชลล์ทุบตีจะแทนที่เนื้อหาของวงเล็บปีกกา
ดังที่เห็นด้านล่างทุบตีไม่ได้แทนที่วงเล็บว่างเปล่าและพวกเขาได้รับการส่งผ่านไปยังคำสั่ง สำหรับfindคำสั่งมันไม่สำคัญ
$ echo {}
{}
$ echo {1}
{1}
$ echo {1,3}
1 3
$ echo '{1,3}'
{1,3}
" are interchangeable"ด้วย " 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"(นิสัยที่ดีเริ่มต้นด้วยการทำให้แน่ใจว่าคุณใช้วิธีที่ถูกต้องแม้ว่าคุณจะเกิดขึ้น (เสมอหรือไม่) อยู่ในระบบที่ทำให้คนกำกวม)
กับเกือบทุกเปลือกล่ามที่มีอยู่อย่างมีความแตกต่างระหว่างไม่มีและ'{}'{}
โดยปกติอัญประกาศเดียวจะใช้เพื่อป้องกันสตริงที่ฝังจากการถูกแทนที่ด้วยอย่างอื่นตัวอย่างเช่น:
'a b' เป็นพารามิเตอร์อักขระสามตัวเดียวโดยไม่มีเครื่องหมายอัญประกาศที่จะเป็นพารามิเตอร์อักขระเดี่ยวสองตัว'$b' เป็นเครื่องหมายดอลลาร์ตามตัวอักษร b ตามตัวอักษรโดยไม่มีการอ้างว่าจะเป็นสิ่งที่ตัวแปร b มีและอาจไม่มีอะไรถ้าไม่ได้ตั้งค่า'!!' เป็นเครื่องหมายอัศเจรีย์ litteral ในขณะที่ไม่ได้พูดถึงและมีเชลล์แบบโต้ตอบบางตัวพวกมันจะขยายไปยังคำสั่งสุดท้ายที่ใส่ไว้ในประวัติ'*' เป็นเครื่องหมายดอกจัน litteral unquoted มันจะถูกแทนที่ด้วยรายการชื่อไฟล์ที่ไม่ซ่อนอยู่ในไดเรกทอรีปัจจุบันขณะที่ค่ามาตรฐาน POSIX มิได้หอยหลัก ( sh(บอร์น) ksh, bash, ash, dash, zsh, csh, tcsh) ขยาย{}ไปยังสิ่งอื่น, คำพูดไม่จำเป็นต้อง
อย่างไรก็ตามมีเปลือกแปลกใหม่ชื่อfishซึ่งเกิดขึ้นเพื่อขยาย{}เป็นสตริงว่างเช่น:
> ps -p %self
PID TTY TIME CMD
5247 pts/1 00:00:00 fish
> echo a {} b '{}'
a b {}
นั่นอาจเป็นเหตุผลที่findเอกสารของGNU แนะนำให้ป้องกัน{}การตีความด้วยเครื่องหมายคำพูดหรือแบ็กสแลช
สำหรับผู้ใช้ส่วนใหญ่ (โดยเฉพาะผู้ที่ใช้เปลือกหอย POSIX) ไม่มีความแตกต่าง
ตามหัวข้อตัวอย่างของ man page สำหรับ GNU find:
ขอให้สังเกตว่าเครื่องหมายวงเล็บอยู่ในเครื่องหมายอัญประกาศเดี่ยวเพื่อป้องกันการตีความเป็นเครื่องหมายวรรคตอนของเชลล์สคริปต์
ฉันคิดว่าผู้แต่งหน้า GNU กำลังทำผิดพลาดอย่างระมัดระวัง แต่ฉันทราบว่าไม่ใช่ทุกตัวอย่างในหน้า man ของพวกเขาที่อ้างถึงเครื่องมือจัดฟัน ตัวอย่างเหล่านี้จาก GNU อย่างเป็นทางการของเอกสารการค้นหายังตัดการอ้างอิง
ในตัวอย่างจากข้อกำหนด POSIX / Single UNIXเครื่องหมายวงเล็บจะไม่ถูกยกมาเมื่อใช้กับ-execตัวเลือก
ด้วย POSIX เปลือกขยายตัวพารามิเตอร์ เกิดขึ้นเฉพาะเมื่อมีพารามิเตอร์พิเศษที่อยู่ภายในวงเล็บ - แต่ไม่ได้อยู่กับการจัดฟันที่ว่างเปล่า
ทุบตีเปลือกรวมถึงการขยายตัวรั้งเป็นคุณลักษณะ (ไม่ใช่แบบพกพา) แต่รูปแบบดังกล่าวจะขยายตัวเพียงเมื่อจุลภาคหรือจุดจะถูกรวมอยู่ในวงเล็บ ทุบตียังใช้เครื่องหมายวงเล็บสำหรับการจัดกลุ่มคำสั่งแต่นี้จะไม่เกิดขึ้นจนกว่าจะมีจริงเป็นกลุ่มของคำสั่งภายในรั้ง
สุดท้ายผมพยายามทำงานfind -exec ls -l {} \;ในsh, dashและtcshแต่ไม่มีเปลือกหอยเหล่านี้ขยาย{}เป็นอะไรอื่น ดังที่คนอื่น ๆ ได้ชี้ให้เห็นfishเชลล์ปฏิบัติ{}เป็นพิเศษ แต่นี่ไม่ใช่ POSIX เชลล์ (ซึ่งผู้สร้างและผู้ใช้พิจารณาว่าเป็นข้อได้เปรียบ) มันไม่เป็นอันตรายต่อการพูดคำว่าเหล็กดัดแต่นักพิมพ์ที่ขี้เกียจที่ไม่ได้ใช้เปลือกหอยก็ไม่ควรรู้สึกผิดกับการละไว้
'{}'แทน{}) เพื่อให้เชลล์ส่ง{}ไปยังคำสั่ง find โดยไม่ตีความมัน (ตามที่กล่าวไว้ข้างต้นโดย @ Charles-Duffy หากคุณใช้ปลา มันจะตีความ{}แต่ไม่'{}'ดังนั้นคุณต้องใช้หลังบนเชลล์นั้น (และอีกหลาย ๆ !) ดังนั้นใช้'{}'เพื่อหลีกเลี่ยงการถูกกัดโดยความคลุมเครือของ{}
ขึ้นอยู่กับไวยากรณ์ของเชลล์ เมื่อมีข้อสงสัยก้องมัน!
เรียกใช้สิ่งนี้
echo '{}'
และนี่.
echo {}
หากพวกมันสร้างเอาต์พุตเดียวกันคำตอบสำหรับเชลล์ของคุณคือใช่ อย่างที่คนอื่นสังเกตมันอย่างน้อยก็จะใช่ในทุบตีและไม่มีในปลา ผลลัพธ์คือสิ่งที่คุณควรศึกษา manpage ของคำสั่งที่ระบุ
หากคุณต้องการทำให้สะดวกคุณสามารถนำหน้าechoทั้งบรรทัดคำสั่งทั้งหมดเพื่อดูคำสั่งจริงพร้อมด้วยอาร์กิวเมนต์ทั้งหมดที่เชลล์ของคุณจะเรียกใช้ อย่างไรก็ตามระวังว่ารายการที่ประกอบด้วยคำสั่งบวกอาร์กิวเมนต์เป็นอาร์เรย์ของสตริงที่แท้จริงแต่ละรายการอาจว่างเปล่าหรือมีช่องว่าง
ตามที่สามารถตรวจสอบได้ด้วยคำสั่ง echo verbose นี้เล็กน้อย (แสดงข้อโต้แย้งที่ยกมา guillemet)
#!/bin/sh
for a in "$@"; do
printf '«%s» ' "$a"
done
echo ''
พิมพ์สิ่งนี้บนบรรทัดคำสั่ง
find 'My Documents and Settings' -type f -exec file {} \;
หมายความว่าสิ่งนี้เพื่อทุบตี:
«find» «My Documents and Settings» «-type» «f» «-exec» «file» «{}» «;»
และสิ่งนี้ในปลา:
«find» «My Documents and Settings» «-type» «f» «-exec» «file» «» «;»
ตามคำแนะนำทั่วไปมันไม่เคยเจ็บที่จะพูด