เหตุใด 'find -delete' จึงลบไฟล์ทั้งหมดในไดเรกทอรีซ้ำ


15

ดังนั้นพฤติกรรมของยูนิกซ์ต่อไปนี้จึงทำให้ฉันเสียค่าใช้จ่ายอย่างมาก:

> touch foo
> touch bar
> ls  
bar  foo
> find . -name '*oo' -delete
> ls
bar
> touch baz
> ls
bar  baz
> find . -delete -name '*ar'
> ls
> #WHAAAT?

มันสมเหตุสมผลขนาดไหน?


2
คำถามนี้เกี่ยวข้องกันอาจน่าสนใจสำหรับผู้อ่านในอนาคต unix.stackexchange.com/questions/101282/…
Bernhard

คำตอบ:


14

บรรทัดคำสั่งของการค้นหาทำจากตัวเลือกประเภทต่าง ๆ ที่รวมเข้ากับรูปแบบของการแสดงออก

findตัวเลือก-deleteคือการกระทำ
ซึ่งหมายความว่าจะถูกเรียกใช้งานสำหรับแต่ละไฟล์ที่ตรงกัน
เป็นตัวเลือกแรกหลังจากเส้นทางไฟล์ทั้งหมดจะถูกจับคู่ ... โอ๊ะโอ!

มันเป็นอันตราย - แต่หน้าคนอย่างน้อยมีคำเตือนใหญ่ :

จากman find:

ACTIONS
    -delete
           Delete  files; true if removal succeeded.  If the removal failed, an
           error message is issued.  If -delete fails, find's exit status  will
           be nonzero (when it eventually exits).  Use of -delete automatically
           turns on the -depth option.

           Warnings: Don't forget that the find command line is evaluated as an
           expression,  so  putting  -delete first will make find try to delete
           everything below the starting points you specified.  When testing  a
           find  command  line  that  you later intend to use with -delete, you
           should explicitly specify -depth in order to avoid later  surprises.
           Because  -delete  implies -depth, you cannot usefully use -prune and
           -delete together.


จากเพิ่มเติมในman find:

EXPRESSIONS
    The expression is made up of options (which affect overall operation rather
    than  the  processing  of  a  specific file, and always return true), tests
    (which return a true or false value), and actions (which have side  effects
    and  return  a  true  or false value), all separated by operators.  -and is
    assumed where the operator is omitted.

    If the expression contains no actions other than  -prune,  -print  is  per‐
    formed on all files for which the expression is true.


เมื่อลองทำสิ่งที่findคำสั่งจะทำ:

เพื่อดูว่าคำสั่งชอบ

find . -name '*ar' -delete

จะลบคุณสามารถแทนที่การกระทำ-deleteด้วยการกระทำที่ไม่เป็นอันตรายเช่น - -flsหรือ-print:

find . -name '*ar' -print

นี่จะพิมพ์ไฟล์ที่ได้รับผลกระทบจากการกระทำ
ในตัวอย่างนี้สามารถพิมพ์ -print ออกได้ -printในกรณีนี้ไม่มีการดำเนินการทั้งหมดเพื่อให้เห็นได้ชัดที่สุดจะถูกเพิ่มโดยปริยาย: (ดูย่อหน้าที่สองของส่วน "EXPRESSIONS" ที่อ้างถึงข้างต้น)


ฉันเดาว่าฉันเป็นแค่คนงี่เง่าที่ไม่อ่านคู่มือก่อน .. แต่มันก็ตรงไปตรงมาที่จะเพิ่ม-deleteธง :-) แต่มีเหตุผลอะไรที่ทุกคนจะทำfind . -deleteมากกว่าrm -rf .? หรือว่าเกิดขึ้นเป็นวิธีfindแยกวิเคราะห์และประมวลผลข้อโต้แย้งของมัน?
mszep

1
โอ้ฉันเห็นด้วยอย่างยิ่งว่าไวยากรณ์นั้นอันตรายมาก- แต่ก็ยากที่จะหลีกเลี่ยงเพราะเป็นเพียงกรณีพิเศษของไวยากรณ์การแสดงออกบรรทัดคอมมอนของการค้นหาซึ่งมีประสิทธิภาพมาก ทรงพลังเหมือนใน " คลั่งลูกโซ่ทรงพลัง "
Volker Siegel

หน้าคู่มือที่ยกมาไม่ได้บอกว่าwarning: use -depth when testing stuff you later want to -deleteคุณไม่ได้ทำตัวอย่างด้านการปฏิบัติของคุณหรือไม่
pqnet

โอ้ใช่ - ปัญหาคือหัวข้อ - ฉันหมายถึงการแสดงการใช้งานแทน -delete เหมือน-nตัวเลือก; คำสั่งแรกไม่ควรใช้งานจริงใด ๆ แน่นอน; ฉันจะไปเปลี่ยนมัน
Volker Siegel

9

ในfindข้อโต้แย้งเรื่องการสั่งซื้อจำนวนมาก

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

บางครั้งfindก็เตือนคุณเกี่ยวกับการสั่งซื้อที่ไม่ดีที่อาจเกิดขึ้น (ตัวอย่างเช่นเมื่อคุณใช้-maxdepthหลังจากการขัดแย้งอื่น ๆ ) แต่คนอื่น ๆ ดูเหมือนว่ามันจะไม่

อะไรfind . -delete -name '*ar'คือ:

  1. ค้นหาไฟล์และไดเรกทอรีตามไดเรกทอรีปัจจุบัน
  2. ลบพวกเขาทั้งหมดตามที่พบ!
  3. จากนั้นดูว่าพวกเขาถูกตั้งชื่อว่า '* ar' (ตอนนี้ไม่มีผลอะไร)

สิ่งที่คุณอาจต้องการทำคือ:

find -name '*ar' -delete

จะทำอย่างไรกับไฟล์ทุกไฟล์ดูว่าตรงกัน'*ar'หรือไม่และตรงตามเงื่อนไขก็จะลบไฟล์

ขออภัยหากคุณพบว่าสายเกินไป

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