การลบไดเร็กทอรีที่มีไฟล์โดยใช้ find


3

ฉันกำลังค้นหารายการไดเรกทอรีสำหรับไฟล์บางไฟล์และฉันต้องการลบไดเรกทอรีที่ไฟล์นั้นมีอยู่

นี่คือสิ่งที่ฉันพยายาม:

find /converter/storage/unmatched/ -size -4b -name '*.mp3' -execdir mv -b `dirname {}` /converter/storage/smallfiles/ \;
mv: cannot move `.' to `/converter/storage/smallfiles/.'

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

คำตอบ:


3

คำสั่งของคุณจะไม่ทำงานตามที่คาดไว้ด้วยเหตุผลหลายประการ:

  1. ทุบตีประเมิน ​`dirname {}`​ ก่อน คำสั่ง find จะถูกเรียกใช้งาน

    สิ่งนี้สามารถแก้ไขได้โดยการเรียกใช้ bash เพื่อประเมินผลลัพธ์ของ dirname คำสั่ง

  2. -execdir เปลี่ยนเป็นไดเร็กทอรีของไฟล์ที่พบก่อนเรียกใช้งานคำสั่ง

    ดังนั้นแม้จะมีไวยากรณ์ที่เหมาะสม dirname {} จะเป็น ..

  3. เนื่องจาก find กำลังดำเนินการผ่านไฟล์ทั้งหมดภายในไดเรกทอรีทั้งหมด (แทนที่จะเป็นไดเรกทอรีเอง) การย้ายไดเรกทอรีที่กำลังประมวลผลอยู่อาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด

    ฉันไม่รู้พอที่จะลงรายละเอียด แต่ตัวอย่างต่อไปนี้ควรอธิบาย

    $ find data -type f -printf "  %p" ; echo
      data/1/b  data/1/a  data/2/b  data/2/a
    $
    $ find data -type f -exec bash -c ' \
    > echo -n "  "mv `dirname {}` backup/
    > ' \; ; echo
      mv data/1 backup/  mv data/1 backup/  mv data/2 backup/  mv data/2 backup/
    $
    $ find data -type f -exec bash -c '
    > echo -n "  "mv `dirname {}` backup/; mv `dirname "{}"` backup/
    > ' \; ; echo
      mv data/1 backup/  mv data/1 backup/
    mv: cannot stat `data/1': No such file or directory
    

    หลังจากย้ายไดเรกทอรีแล้ว data/1ค้นหาพบว่ากำลังประมวลผลเนื้อหา ซึ่งทำให้ข้อความแสดงข้อผิดพลาดตั้งแต่ค้นหาดำเนินการ mv สำหรับทุกไฟล์ใน data/1แต่ทำงานได้ดีอย่างอื่น เมื่อประมวลผลเสร็จแล้ว data/1หาได้รับ "หลงทาง" อย่างใด

  4. ในขณะที่ค้นหาจัดการตัวละครที่เป็นไปได้ทั้งหมดที่มีความหมายพิเศษอย่างถูกต้องถ้า {} เกิดขึ้นเป็นอาร์กิวเมนต์ธรรมดาที่จะค้นหาคำสั่งในตัวอย่าง 3 จะไม่สามารถดำเนินการได้อย่างถูกต้องหากเช่นมีช่องว่างเกิดขึ้นในเส้นทาง เพื่อหลีกเลี่ยงปัญหานี้ทั้งการส่งออกอาร์กิวเมนต์ของ dirname จะต้องมีการยกมา

    การใช้ mv "`dirname "{}"`" (หรือ mv "$("{}")"ซึ่งมีความชัดเจนมากขึ้น) จะทำงานได้ดีกับช่องว่าง แต่สามารถนำไปสู่ผลกระทบร้ายแรงโดยทั่วไป 1 .

  5. mv -b ไม่สามารถสำรองข้อมูลไดเรกทอรีได้เฉพาะไฟล์เท่านั้น

เมื่อคุณพบว่าตัวเองปัญหา 3 จะเกิดขึ้นก็ต่อเมื่อคุณพยายาม ย้าย ไดเรกทอรี แต่ไม่ใช่ถ้าคุณเช่นลบออก ดังนั้นทางออกที่ง่ายและปลอดภัยในการแก้ไขปัญหา 3 (ซึ่งแก้ไขปัญหาที่ 5 ในกระบวนการ) กำลังย้ายไดเรกทอรีที่ตรงกันลงในไฟล์ zip 2

ปัญหาที่ 4 สามารถแก้ไขได้โดยผ่าน {} เป็นอาร์กิวเมนต์เพื่อทุบตีและเข้าถึงมันเป็น $0.

คำสั่ง

find /converter/storage/unmatched/ -type f -size -4b -name '*.mp3' \ -exec bash -c ' \
  zip -0mqr smallfiles.zip "$(dirname "$0")"\
' {} \;

จะทำงานได้ตามที่คาดไว้แม้ว่าจะยังคงสร้างข้อความแสดงข้อผิดพลาดเมื่อพยายามย้ายไดเรกทอรีมากกว่าหนึ่งครั้ง

จะใช้วิธีที่สะอาดกว่านี้ (เช่นไม่มีข้อความแสดงข้อผิดพลาด) find -depth -type d เพื่อผ่านไดเรกทอรีเอง 3

สำหรับแต่ละไดเรกทอรีเราสามารถใช้

find "$0" -maxdepth 1 -type f -size -4b -name '*.mp3' -printf 1 -quit

ปริ้น 1 ถ้าเพียง แต่ควรลบออก 4 และทดสอบ ( [ ) เพื่อตรวจสอบว่าพบพิมพ์ 1 .

คำสั่ง

find /converter/storage/unmatched/ -depth -type d -exec bash -c ' \
  [ $(find "$0" -maxdepth 1 -type f -size -4b -name '*.mp3' -printf 1 -quit) ] \
  && echo zip -0mqr smallfiles.zip "$0"\
  ' {} \;

จะต้องมีผลที่ต้องการ


1 หากชื่อไดเรกทอรีภายใน ไม่มีที่เปรียบ ประกอบด้วยอักขระขึ้นบรรทัดใหม่หนึ่งตัว "$(dirname "{}")" จะประเมินให้ unmatched และ $(dirname {}) จะประเมินให้ . (เช่นโฟลเดอร์ที่คุณเรียกใช้งานคำสั่ง)!

2 แม้จะไม่มีการบีบอัดไฟล์ แต่มันจะใช้เวลานานกว่ามากในการย้ายไฟล์ถ้าไฟล์มีขนาดใหญ่ เนื่องจากโฟลเดอร์ปลายทางของคุณถูกเรียก smallfiles ฉันสงสัยว่านี่จะไม่เป็นปัญหา

3 สวิตช์ความลึกทำให้กระบวนการค้นหาเนื้อหาของแต่ละไดเรกทอรีก่อนประมวลผลตัวไดเรกทอรี นี่เป็นการหลีกเลี่ยงข้อความแสดงข้อผิดพลาดที่เราได้รับด้วยวิธีแรก

4 -quit สวิทช์ทำให้หยุดค้นหาหลังจากหาคู่แรก มันไม่จำเป็นอย่างเคร่งครัด แต่มันอาจเพิ่มความเร็วขึ้นเล็กน้อย


การรันด้วย echo จะส่งเอาต์พุตคำแนะนำที่ถูกต้อง แต่จะรันด้วย mv ย้ายเพียงไดเรกทอรีเดียวแล้วบ่น No such file or directory. ฉันค่อนข้างแน่ใจว่าสิ่งนี้เกี่ยวข้องกับความเข้าใจในการค้นหาของฉัน คุณสามารถชี้ฉันไปในทิศทางที่ถูกต้องได้ไหม
Josh Smeaton

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

มันไม่ได้เป็นเพียงไดเรกทอรีเดียว เปลี่ยนเป็น rm ทำเคล็ดลับโดยไม่มีข้อผิดพลาดซึ่งเป็นสิ่งที่ฉันได้เล็งไปยัง ขอบคุณสำหรับมือ ฉันต้องการทราบลำดับของการทดแทน / การประเมินผล
Josh Smeaton

ฉันมีสมมติฐาน (ที่ฉันจะตรวจสอบในวันพรุ่งนี้): หลังจากประมวลผลไดเรกทอรีแรกที่ตรงกันให้ค้นหา - ไม่ทราบว่าไดเรกทอรีถูกย้ายแล้ว - ไปยังโฟลเดอร์หลักของมัน ( smallfiles ) หากไม่มีไฟล์อื่น ๆ ให้ดำเนินการจะออกทันที
Dennis

no such file or directory เกิดขึ้นสำหรับทุก ๆ ไฟล์ที่ต่อเนื่องกัน สำหรับโฟลเดอร์ 100 โฟลเดอร์จะย้ายหนึ่งโฟลเดอร์จากนั้นเกิดข้อผิดพลาด 99 ครั้ง
Josh Smeaton
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.