ในเอกสารฉันเห็นการใช้งานทั้งสองวิธี:
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» «» «;»
ตามคำแนะนำทั่วไปมันไม่เคยเจ็บที่จะพูด