ความแตกต่างระหว่าง '{}' และ {} ในคำสั่ง find หรือไม่


18

ในเอกสารฉันเห็นการใช้งานทั้งสองวิธี:

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

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

4
แน่นอนดูเหมือนว่าไม่มีส่วนเกี่ยวข้องกับการค้นหาคำสั่งและเกี่ยวข้องกับการอ้างคำสั่งที่เหมาะสม
Zoredache

1
ลองกับปลามากกว่าทุบตี
Charles Duffy

คำตอบ:


24

สำหรับbashเปลือก'{}'และ{}สามารถใช้แทนกันได้ นี่ไม่ใช่กรณีที่มีเชลล์ทั้งหมด (เช่นfish)

findใส่อาร์กิวเมนต์ในราคาเดียวอย่างชัดเจนบ่งชี้ว่าวงเล็บปีกกาควรจะส่งไป บางครั้งเชลล์ทุบตีจะแทนที่เนื้อหาของวงเล็บปีกกา

ดังที่เห็นด้านล่างทุบตีไม่ได้แทนที่วงเล็บว่างเปล่าและพวกเขาได้รับการส่งผ่านไปยังคำสั่ง สำหรับfindคำสั่งมันไม่สำคัญ

$ echo {}
{}

$ echo {1}
{1}

$ echo {1,3}
1 3

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

4
ไม่สำคัญกับการทุบตี เรื่องอะไรกับปลา
Charles Duffy

1
ฉันจะแทนที่" 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"(นิสัยที่ดีเริ่มต้นด้วยการทำให้แน่ใจว่าคุณใช้วิธีที่ถูกต้องแม้ว่าคุณจะเกิดขึ้น (เสมอหรือไม่) อยู่ในระบบที่ทำให้คนกำกวม)
Olivier Dulac

9

กับเกือบทุกเปลือกล่ามที่มีอยู่อย่างมีความแตกต่างระหว่างไม่มีและ'{}'{}

โดยปกติอัญประกาศเดียวจะใช้เพื่อป้องกันสตริงที่ฝังจากการถูกแทนที่ด้วยอย่างอื่นตัวอย่างเช่น:

  • '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 แนะนำให้ป้องกัน{}การตีความด้วยเครื่องหมายคำพูดหรือแบ็กสแลช


9

สำหรับผู้ใช้ส่วนใหญ่ (โดยเฉพาะผู้ที่ใช้เปลือกหอย 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 หากคุณใช้ปลา มันจะตีความ{}แต่ไม่'{}'ดังนั้นคุณต้องใช้หลังบนเชลล์นั้น (และอีกหลาย ๆ !) ดังนั้นใช้'{}'เพื่อหลีกเลี่ยงการถูกกัดโดยความคลุมเครือของ{}
Olivier Dulac

6

ขึ้นอยู่กับไวยากรณ์ของเชลล์ เมื่อมีข้อสงสัยก้องมัน!

เรียกใช้สิ่งนี้

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» «» «;»

ตามคำแนะนำทั่วไปมันไม่เคยเจ็บที่จะพูด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.