ฉันจะควบคุมคำสั่ง UNIX ได้อย่างไร


11

ฉันคิดว่าฉันค่อนข้างก้าวหน้าในการใช้การค้นหา แต่ทุกครั้งที่ฉันใช้ฉันไม่สามารถใช้ชีวิตของฉันได้จำวิธีการปิดตัวเลือก -exec ฉันใช้เวลาอ่านหนังสือทุกครั้งที่ใช้งาน ฉันแค่ใช้มันไม่พอหรือคาดหวังตัวเองมากเกินไปหรือเปล่า? ให้เริ่มต้นด้วยตัวอย่างทั่วไปที่ทำให้ฉันผิดหวัง

โครงสร้างไดเรกทอรีมีไฟล์ที่มีสิทธิ์ที่ไม่ถูกต้องไฟล์ที่ซ่อนลิงก์สัญลักษณ์ ฯลฯ ฉันต้องการเปลี่ยนความเป็นเจ้าของให้คุ้มค่า

find . -type f -exec chown username {} \;
find . -type d -exec chown username {} \;
find . -type d -exec chgrp usergroup {} \;
find . -type f -exec chgrp usergroup {} \;

(ยกโทษให้ฉันถ้าตอนจบอยู่ข้างหลัง ... ฉันดูมันเมื่อชั่วโมงก่อนและฉันก็ยังไม่แน่ใจ)

แต่ฉันกลัวที่จะเรียกใช้เพราะเมานต์ลิงก์สัญลักษณ์ ฯลฯ ฉันได้ทำจุดสูงสุดของ chmod * และทำให้มันเพิ่มขึ้นเมื่อฉันก่อน ฉันรู้ -xdev จะละทิ้งพาร์ทิชันข้าม แต่ฉันไม่แน่ใจว่าจะเกิดอะไรขึ้นกับไฟล์ที่อยู่ในไดเรกทอรีซึ่งเป็นลิงค์สัญลักษณ์

แล้วสัตว์ร้ายตัวนี้ที่สามารถฆ่าไฟล์สำคัญได้อย่างไร

อัปเดตการตัดแต่งคำแนะนำที่ดีที่สุดด้านล่างและสรุป:

  1. มีการเชื่อมโยงไดเรกทอรีฝึกและเชื่อมต่อกับไดเรกทอรีฝึกอื่น ๆ
  2. ใช้ xargs แทนคำสั่ง exec ที่ไม่ง่าย
  3. ใช้ -exec echo {} เพื่อสติและความปลอดภัย
  4. เครื่องหมายทวิภาคกึ่งพิเศษและคุณกำลังหลบหนีดังนั้นตัวหลบหนีจึงเป็นตัวแรก
  5. คำสั่ง - หรือสามารถช่วยคุณรวมเกณฑ์การเลือก

ฉันสับสนเล็กน้อยเกี่ยวกับ print0 แต่ xargs มักจะไม่ค่อยเข้าใจง่ายในตอนแรกที่ฉันพยายามหลีกเลี่ยง


1
ฉันจำไม่ได้เหมือนกันดังนั้นฉันจึงใส่เข้าไปใน xargs
resonator

2
เมื่อคุณพอใจกับการสร้างคำสั่งที่ถูกต้องให้ลองรันด้วย + แทน \; มันจะทำงานได้เร็วขึ้นด้วย + เพราะคำสั่ง exec จะถูกเรียกใช้บ่อยครั้งกว่ามาก
wzzrd

wzzrd, เคล็ดลับที่ดีเกี่ยวกับการใช้ + มากกว่า \;
Daniel Lawson

คำตอบ:


19

เท่าที่-execไวยากรณ์ไปคุณสามารถทำหลายคนยอมแพ้และใช้xargs:

find . -type f | xargs chown username

(หรือรุ่นที่มีช่องว่างและอื่น ๆ ที่ไม่ใช่เรื่องไร้สาระในรุ่นปลอดภัย)

find . -type f -print0 | xargs -0 chown username

หรือเพื่อพยายามจดจำสิ่งที่ถูกต้องเกี่ยวกับเครื่องหมายอัฒภาคสิ่งที่คุณต้องเจาะเข้าไปในหัวของคุณก็คือคุณกำลังใช้เครื่องหมายอัฒภาคเพื่อยกเลิกคำสั่งที่-execทำงานอยู่และคุณต้องหนีเครื่องหมายอัฒภาคเพราะมันพิเศษ bashความหมาย ซึ่งเป็นสาเหตุว่าทำไมเครื่องหมายเซมิโคลอนแบ็กสแลช คุณดูเหมือนจะมี{}ส่วนทดแทน

ในการฆ่าไฟล์และอื่น ๆ หากคุณกำลังใช้งานสิ่งที่มีขนาดใหญ่และอันตรายอย่างที่คุณกำลังพูดถึงให้ทำสิ่งนี้ก่อน:

find . -type f -exec echo chown username {} \;

และตรวจสอบผลลัพธ์ นี่คือ "dry run" ซึ่งคุณจะเห็นคำสั่งที่มันจะทำงานถ้าคุณปล่อยให้มัน เป็นการปฏิบัติที่ดีอย่างแน่นอน จะไม่ช่วย.*ปัญหา แต่คุณรู้ว่าจะไม่ทำอย่างนั้นตอนนี้ :)


1
+! สำหรับการฝึกแบบ 'echo' ในระยะแห้ง ฉันมักจะใช้นี้สำหรับการเปลี่ยนแปลงครั้งใหญ่
สตีฟเขลา

3

ฉันประหลาดใจที่ไม่มีใครพูดถึงตัวเลือกต่อไปนี้:

find . -type f -ok chown username {} \;

ไวยากรณ์นี้จะยืนยันคำสั่งก่อนดำเนินการ มันจะทำงานได้ดีที่สุดถ้าคุณคาดหวังว่าการจับคู่ของคุณจะมีจำนวนไฟล์ค่อนข้างน้อยเพราะจะมีการแจ้งให้แต่ละไฟล์ทราบ

บางคำตอบพูดถึงxargsแต่ด้วย GNU พบว่าไม่จำเป็นเช่นกัน:

find . -type f -exec chown username {} \+

โปรดทราบว่าโดยทั่วไปแล้วเครื่องหมาย + ไม่จำเป็นต้องหลบหนี แต่เป็นการดีที่จะทำเช่นนี้ได้


คุณช่วยอธิบายลักษณะของเครื่องหมายบวก ... มันทำอะไรกันแน่? เชลล์ประมวลผลมันหรือคำสั่ง ฉันคิดว่าฉันจะดาวน์โหลดซอร์สโค้ดสำหรับ gnu-find เพราะนี่เป็นหัวข้อที่น่าสนใจ
ojblass

find กำลังประมวลผลมัน อ่านคนค้นหาเพื่อหาข้อมูลเพิ่มเติมเกี่ยวกับตัวเลือกนั้น
Kamil Kisiel

3

นี่คือสิ่งที่มนุษย์มีไว้สำหรับ: มันอาจเป็นเรื่องยากที่จะจำสิ่งต่าง ๆ นั่นคือเหตุผลที่คำสั่ง * nix รวมหน้าคน man findคุณสามารถเพียงแค่เสมอตรวจสอบการดำเนินการในส่วนของหน้าคนสำหรับการแจ้งเตือนเกี่ยวกับไวยากรณ์ไปนี้: แม้ว่าหน้าคนอาจดูเหมือนจะไม่เป็นมิตร แต่เมื่อคุณเก่งในการอ่านพวกเขาพวกมันมีประโยชน์มาก

สร้าง Front-End หรือ Wrapper: เมื่อฉันต้องการดีขึ้นที่ GNU find ฉันเขียนส่วนหน้า GUI สำหรับการค้นหาที่สร้างคำสั่ง find ด้วย python, glade และ pygtk นี่คือการออกกำลังกายที่ดีถ้าต้องการทำความรู้จักกับมันจริงๆ

มีไดเรกทอรีฝึกปฏิบัติ: สุดท้ายฉันมักจะมีไดเรกทอรี 'เศษซาก' ในบ้านของฉันสำหรับเล่นกับคำสั่งที่ทรงพลังเมื่อสิ่งที่ 'echo' ไม่ได้ตัด คุณสามารถใช้การขยายตัวของเชลล์เพื่อทำพวงไฟล์อย่างรวดเร็วด้วยสิ่งต่อไปนี้:

for i in {1..100}; do touch "$i"; done

ไดเรกทอรีฝึกที่แปลกประหลาดเป็นสิ่งที่ฉันไม่เคยพิจารณามาก่อน
ojblass

1

คุณยังสามารถรวมการค้นหานิพจน์กับตัวดำเนินการ 'และ' หรือ 'หรือ' - และเป็นนัย:

find . -type f -name "plainfile" ...

เป็นเช่นเดียวกับ

find . -type f -and -name "plainfile" ...

ผู้ประกอบการหรือสามารถลดรายการ 4 คำสั่งของคุณเป็น 2:

find . -type d -or -type f ...

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

find . -type d -or -type f -exec chown username:usergroup '{}' \;

สิ่งที่พบกับธุรกิจหรือ [Sic]
ojblass

@ojblass: find รวมนิพจน์ที่ใช้ 'และ' หรือ 'หรือ' หรือ 'โดยปริยายหากไม่มีการระบุ' -and 'หรือ' -or 'หรือ' -and 'โดยปริยาย ดังนั้นพิมพ์ 'find -type d -type f' จะไม่พบสิ่งใดเพราะไม่มีสิ่งใดเป็นไดเรกทอรีและไฟล์
Steve Folly

0

เมื่อปิดฉันคิดว่าใช้ เช่นเดียวกับภาษาการเขียนโปรแกรมจำนวนมากแล้วหนีออกมา เพียงจำไว้ว่าจะต้องมีการหลบหนีและมันมาถึงคุณได้อย่างง่ายดาย


0

ขึ้นอยู่กับรุ่นของการค้นหาที่คุณใช้มีตัวเลือกต่าง ๆ ที่อาจช่วยคุณได้ GNU find น่าจะมีประสิทธิภาพที่สุดและอาจช่วยคุณได้ในคำถามที่สอง (โดยนัย)

ตัวอย่างเช่น - พฤติกรรมเริ่มต้นไม่ได้เป็นการอ้างอิงถึงลิงก์สัญลักษณ์ แต่คุณสามารถลบล้างสิ่งนั้นได้ และตัวเลือกเมานท์ - หยุดพบว่าข้ามจุดเชื่อมต่อ

ดูในหน้าคนท้องถิ่นของคุณ


0

บางคนยืนยันว่าตัวเลือก xargs นั้นเร็วกว่าตัวเลือก -exec เพราะมันจะไม่รันคำสั่งหนึ่งครั้งสำหรับแต่ละไฟล์ แต่ฉันไม่ต้องกังวลเกี่ยวกับสิ่งนั้นยกเว้นงานขนาดใหญ่ที่ใช้เวลาไม่มาก

โดยส่วนตัวฉันมักจะเรียกใช้การค้นหาโดยไม่มีผู้บริหาร

find /path/to/dir -name whatever

ตรวจสอบให้แน่ใจว่าผลลัพธ์ที่ถูกต้องแล้วเรียกใช้คำสั่งของฉันในรายการนั้น

chown user:group `find /path/to/dir -name whatever`

ตัวอย่างที่สมบูรณ์แบบของวิธีการ "ไม่" ในการทำสิ่งต่าง ๆ ชื่อไฟล์ที่มีช่องว่าง
เอียน Kelling

ใช่ว่าเป็นปัญหาที่อาจเกิดขึ้นซึ่งฉันควรจะได้รับการยอมรับ อย่างไรก็ตามจุดของฉันเกี่ยวกับการอ่านผลลัพธ์การค้นหาก่อนที่จะดำเนินการใด ๆ ที่คุณจะพบช่องว่างหรือบ้าชื่อไฟล์อื่น ๆ
theotherreceive

0

สำหรับบาง shells (ไม่ใช่ bash) escape {} สำหรับการทำงานที่เหมาะสม

\{\} or '{}'

ค้นหาด้วยตนเองเป็นสิ่งที่ดีสำหรับการเรียนรู้การค้นหา


ไม่คุณทำไม่ได้; ค้นหาวิ่งได้ดีกับ {} ตามที่เป็นอยู่ เป็นส่วนหนึ่งของคำสั่ง find: เป็นโทเค็นที่ถูกแทนที่ด้วยผลลัพธ์ของคำสั่ง find พวกเขาหมายถึงบางสิ่งบางอย่างในทุบตีเมื่อกำหนดฟังก์ชั่นหรือตัวแปรโทรดังนั้นคุณสามารถใช้พวกเขาเช่นเดียวกับในคำถามเดิม
wzzrd

มันมาจากหน้าคน ฉันอัปเดตเพื่อบอกว่าใช้ไม่ได้กับการทุบตี
Ian Kelling

0

ก่อนที่คุณจะทำอะไรเช่นนี้ให้แน่ใจว่าไดเร็กตอรี่ที่ใช้คำสั่งนี้ไม่อยู่ในระบบไฟล์เดียวกับ / usr หรือ / etc. (ไม่เช่นนั้นถ้าฉันมีฮาร์ดลิงก์ไปยัง / etc / passwd หรือ to / bin / sh ในโฮมไดเร็กตอรี่ของฉันคุณเพิ่งให้สิทธิ์การเป็นเจ้าของกับฉันและเป็นผลข้างเคียงที่ฉันมีตอนนี้)

หากคุณต้องการเรียกคืนผ่านไดเรกทอรีและ chown ไฟล์ / ไดเรกทอรีทั้งหมดง่าย ๆ

chown -Rh user: usergroup user /

จะทำมัน ตรวจสอบให้แน่ใจว่าคุณใช้ -h หรือ chown จะตามลิงก์สัญลักษณ์


ฉันไม่คิดว่านี่เป็นแพลตฟอร์มข้าม ยังล้มเหลวด้วย 247K ของไฟล์ที่แสดงโดยสภาพแวดล้อมการปฏิบัติของฉัน ฉันไม่แน่ใจว่าทำไม
ojblass

ฉันคิดว่าคุณพบข้อผิดพลาดมากกว่าที่คุณพบปัญหาเกี่ยวกับ crossplatform เวอร์ชันใดและสถานะการออกเมื่อมันล้มเหลว เท่าที่ฉันสามารถบอกได้ครั้งแรกที่เกิดขึ้นในรุ่น bsd ต้น; มันแน่นอนใน sunos 5.3 และ ultrix และ irix มีการประมวลผลจำนวนเท่าใดก่อนที่จะล้มเหลว
chris

คุณใช้งานได้บน AIX 5.3, AIX 5.2 แต่ไม่ใช่ AIX 4.3, NCR, HP 11, HP 10.20 หรือการแจกแจง DSL ของฉัน ในทุกกรณีดูเหมือนว่าจะล้มเหลวที่หรือใกล้กับไฟล์ 60k
ojblass
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.