'rm. *' เคยลบไดเรกทอรีหลักหรือไม่


53

นิพจน์.*ถูกขยายโดย bash เพื่อรวมไดเรกทอรีปัจจุบันและพาเรนต์:

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

ถ้าฉันใช้rm -rf .*Debian โดยใช้ GNU bash version 4.2.36(1)-releaseและrmจากrm (GNU coreutils) 8.13ฉันได้รับข้อความนี้:

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

นี่คือสิ่ง GNU หรือเป็น POSIX? มีระบบ * nix ที่คำสั่งด้านบนจะลบ.และเงียบ ๆ..ไหม?

นอกจากนี้นี่เป็นคุณสมบัติด้านความปลอดภัยของเชลล์หรือของrmคำสั่งเองหรือไม่?


4
ฉันรู้ว่าคำถามนี้ในบริบทของrmแต่ฉันคิดว่ามันเป็นมูลค่าการกล่าวขวัญว่าคุณยังสามารถมีผลที่ไม่คาดคิดกับchmod, chownฯลฯ .*เมื่อจับคู่
Aaron Copley

คำตอบ:


59

ล่าสุด ( ณ 2017) รุ่นของข้อมูลจำเพาะ POSIX สำหรับrmยูทิลิตี้ที่นี่ (และก่อนหน้านี้หนึ่งมี ) และห้ามลบและ...

หากไฟล์จุดใดจุดหนึ่งหรือจุดจุดถูกระบุเป็นส่วน basename ของตัวถูกดำเนินการ (นั่นคือองค์ประกอบชื่อพา ธ สุดท้าย) หรือถ้าตัวถูกดำเนินการแก้ไขไปยังไดเรกทอรีราก, RM จะเขียนข้อความวินิจฉัยข้อผิดพลาดมาตรฐานและไม่ทำอะไรเลย มากขึ้นด้วยตัวถูกดำเนินการ

ตามที่ระบุไว้โดย @jlliagre ส่วนที่เกี่ยวกับ/การเพิ่มใน SUSv4

ข้อมูลจำเพาะ Unix ที่เปิดเผยต่อสาธารณชนที่เก่าแก่ที่สุดที่ฉันสามารถหาได้ ( XPF4 CAE rev2 (1994)) ได้ระบุไว้แล้ว.และ..ไม่สามารถลบออกได้แม้ว่าความคิดเห็นใน GNU fileutils changelog แนะนำว่าเป็นกรณีใน POSIX รุ่นเก่า

โปรดทราบว่ามันใช้กับdir/..และ../เช่นกัน แต่การใช้งานบางอย่าง (รวมถึงการรับรอง UNIX เช่น Solaris 11 และ macOS) ยังคงไม่ได้ป้องกันrm -rf ../หรือrm -rf .*/)

ประวัติศาสตร์

ก่อนเริ่ม

-rตัวเลือกที่จะrmถูกเพิ่มเข้ามาในระบบปฏิบัติการยูนิกซ์ V3 (1973) แม้ว่ามันจะเป็นเพียงการลบเนื้อหาของไดเรกทอรีที่คุณยังคงจำเป็นต้องใช้rmdirในการลบไดเรกทอรี

สิ่งนั้นเปลี่ยนไปใน Unix V7 (1979, รุ่นที่เปิดตัว Bourne shell และ Unices ส่วนใหญ่ได้รับมา) rm -rตอนนี้ลบไดเรกทอรีเช่นกันและจะไม่ลบ..ทรีไดเรกทอรี หน้าคนฯ :

ห้ามมิให้ลบไฟล์..เพื่อหลีกเลี่ยงผลกระทบต่อต้านสังคมโดยไม่ได้ตั้งใจทำบางสิ่งเช่นrm -r .*นั้น

(แม้ว่าบางคนอาจโต้แย้งว่าrm -r .*ยังคงต่อต้านสังคมเพราะมันลบทุกอย่างเพราะ.รวมอยู่)

มันก็ยังยอมรับที่จะลบ.แม้ว่ามันจะไม่ยกเลิกการเชื่อมโยง.หรือ..รายการ ดังนั้นจึงrm -r .เป็นวิธีที่มีประสิทธิภาพในการล้างไดเรกทอรีปัจจุบัน

นอกจากนี้ทราบว่าการป้องกันเป็นเพียงสำหรับตัวอักษร..โต้แย้งไม่ได้สำหรับการหรือdir/.. ./..ดังนั้นrm -rf ./.*จะยังคงลบทุกอย่างในไดเรกทอรีหลักซ้ำ

เป็นที่น่าสนใจที่จะเห็นว่านั่นเป็นวิธีที่จะแก้ไขข้อผิดพลาด / ความผิดพลาดที่ globs สามารถรวม.และ..ในการขยายตัวของพวกเขา ที่ได้รับการแก้ไขใน Forsyth shell (พื้นฐานสำหรับ Minix shell และ pdksh เดิม) ในช่วงปลายยุค 80, zsh(1990) และfish(2005) แต่ไม่ใช่ shell อื่น ๆ และโดยเฉพาะอย่างยิ่งไม่ใช่shภาษาPOSIX ที่ต้องการการขยาย.*รวม.และ..ถ้า พวกเขาจะถูกส่งกลับโดยreaddir()( bashแก้ไขปัญหาส่วนหนึ่งเท่านั้นshopt -s dotglobที่ที่ globs (ยกเว้น.xxxคน) ไม่รวม.หรือหรือ..ด้วยkshและคุณสามารถแก้ไขได้โดยการทำFIGNORE='@(.|..)')

เมื่อการห้าม.เช่นกันถูกเพิ่มเข้ามาไม่ชัดเจนและแตกต่างกันไปตามแต่ละยูนิกซ์ ข้อค้นพบบางประการด้านล่าง

BSDs

การห้าม.ถูกเพิ่มเข้ามาระหว่าง 2.9BSD (1983) และ 2.10BSD (1987) และระหว่าง 4.2BSD (1983) และ 4.3BSD (1986) (ดูการเปลี่ยนแปลงนี้ประทับเวลา 1985 ใน unix-history-repo )

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'\n");

สำหรับdir/.และdir/..ดูการเปลี่ยนแปลงนี้ในปี 1988 (BSD 4.3 สุทธิ / 1)

จนถึงวันนี้rmFreeBSD (และอนุพันธ์เช่น macOS) ยังคงว่างเปล่าไดเรกทอรีปัจจุบันหรือไดเรกทอรีหลักขึ้นอยู่กับrm -rf ./หรือrm -rf ../(สำคัญสำหรับrm -rf .*/)

ระบบ V

ฉันไม่ได้รับข้อมูลมากนักเนื่องจาก AT&T Unix ไม่ได้ใช้แหล่งข้อมูลหรือไบนารีสำหรับ V7 ในคู่มือออนไลน์ HPUX (ตาม System III) ยังคงกล่าวถึงว่าห้ามเพียงอย่างเดียว..ในขณะที่มันห้ามอย่างมีประสิทธิภาพซึ่งเป็นสิ่งบ่งชี้ว่าอย่างน้อย SysIII ไม่ได้ห้ามการลบ.( แก้ไข : ตอนนี้ดูซอร์สโค้ดSysIIIrmแล้ว แทบไม่มีการเปลี่ยนแปลงตั้งแต่ Unix V7)

คู่มือออนไลน์อื่น ๆ ทั้งหมดที่ฉันได้ตรวจสอบพูดถึงการลบ.หรือ..ถูกห้ามซึ่งคาดว่าจะเป็นไปตาม POSIX

โซลาริสrmยังคงเทไดเรกทอรีปัจจุบันหรือผู้ปกครองเมื่อหรือrm -rf ./rm -rf ../

GNU

การเปลี่ยนแปลงก่อนหน้าสำหรับไฟล์ GNUมีข้อมูลประวัติทั้งหมด

ในขณะที่เดิมไม่ได้ลบ.หรือ..ถูกห้าม..ถูกห้ามก่อนแล้วทั้งสอง (รวมถึงdir/.) ทั้งหมดระหว่างปี 1990 และ 1991

อื่น ๆ

อย่างที่เราเห็นในzshการขยายตัวของ.*(หรือกลมใด ๆ ) ไม่เคยมี.หรือ..(แม้ในshโหมดการจำลอง) rmbuiltin (ซึ่งคุณจะได้รับถ้าคุณzmodload zsh/files) ดังนั้นจึงไม่รักษา.หรือ..เป็นพิเศษ ดังนั้นด้วยความที่zshในตัวคุณสามารถrm -rf .หรือrm -rf ..จะว่าง.หรือ..แต่rm -rf .*จะไม่ลบหรือ...

ใน busybox rmการห้ามการลบ.และ..ถูกเพิ่มใน 0.52 (2001)


แปลกที่ดูเหมือนว่าจะระบุว่าrm -rf . /(สังเกตพื้นที่) ควรพิมพ์สองคำเตือน (สำหรับ.และ/) และออก แต่เราดูเหมือนจะได้รับคำถามถามวิธีการกู้คืนจากที่ทุกสองสามเดือน
เควิน

6
@Kevin ระบบทั้งหมดไม่ได้เป็นไปตาม POSIX และข้อ จำกัด ของไดเรกทอรีรากถูกเพิ่มอย่างชัดเจนใน POSIX รุ่นล่าสุดเท่านั้น
jlliagre

@ jlliagre ฉันเห็น โดยทั่วไปแล้ว GNU พยายามที่จะใช้ POSIX (ส่วนขยาย + ของหลักสูตร) ​​และฉันคิดว่าพวกเขาต้องการที่จะใส่เข้าไปในนี้ แต่ถ้ามันค่อนข้างใหม่ที่จะอธิบาย
เควิน

2
@ สตีเฟน: ถูกต้อง แต่ฉันยังคงเพิ่มขนาดใหญ่ "ใช่มันอาจเกิดขึ้นได้! แต่ ... " ในตอนต้นของคำตอบของคุณเพื่อให้ผู้คนสงสัยอย่างแน่นอนในบางคน (แก่กว่าหรือไม่ใช่แค่นั้น) -POSIX ที่สอดคล้องกับ) ระบบสามารถลบพาเรนต์ไดเร็กทอรีได้ ฉันพยายามชี้ให้เห็นความเป็นไปได้เหล่านั้นเสมอ (เช่นฉันพยายามอยู่ในที่ปลอดภัยแม้ว่าบางครั้งมันจะทำให้การอ่าน / จำคำตอบยากขึ้น) ^^
Olivier Dulac

1
@ MartinSchröderบน BSDs ถูกเพิ่มที่ไหนสักแห่งระหว่าง 2.8BSD และ 2.10BSD (ก่อนหน้าเท่านั้น ".. " ถูกห้ามเหมือนใน UnixV7) และระหว่าง 3BSD และ 4.3RENO สำหรับระบบ SysV มันชัดเจนน้อยกว่า คู่มือ HPUX เช่นอ้างว่าห้าม ".. " เท่านั้น แต่จะห้ามทั้งสองอย่าง "." และ ".. " เป็นเพียงคู่มือที่ไม่ทันสมัย
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.