ย้ายไฟล์ซ้ำใน sub-dirs ไปยัง sub-dirs ใหม่ที่มีชื่อเดียวกัน


2

ฉันมีชุดของไฟล์ทั้งหมดที่ลงท้ายด้วยสตริงเดียวกันเช่น: *_ext.datตั้งอยู่ในหลาย sub-dirs พร้อมกับไฟล์อื่น ๆ หลายใน dir หลักที่กำหนด นี่คือโครงสร้าง:

/main_dir/subdir1/file11_ext.dat
/main_dir/subdir1/file12_ext.dat
/main_dir/subdir1/file13_ext.dat
/main_dir/subdir1/file14_other.dat
/main_dir/subdir1/file15_other.dat

/main_dir/subdir2/file21_ext.dat
/main_dir/subdir2/file22_ext.dat
/main_dir/subdir2/file23_ext.dat
/main_dir/subdir2/file24_other.dat
/main_dir/subdir2/file25_other.dat

/main_dir/subdir3/file31_ext.dat
/main_dir/subdir3/file32_ext.dat
/main_dir/subdir3/file33_ext.dat
/main_dir/subdir3/file34_other.dat
/main_dir/subdir3/file35_other.dat

ฉันต้องการที่จะย้ายซ้ำเฉพาะไฟล์ที่ลงท้าย*_ext.datเป็นผบหลักใหม่new_dirเคารพโครงสร้างย่อย dir เพื่อให้ไฟล์ที่จะสิ้นสุดในโครงสร้าง dir เทียบเท่าเช่นนี้

/new_dir/subdir1/file11_ext.dat
/new_dir/subdir1/file12_ext.dat
/new_dir/subdir1/file13_ext.dat

/new_dir/subdir2/file21_ext.dat
/new_dir/subdir2/file22_ext.dat
/new_dir/subdir2/file23_ext.dat

/new_dir/subdir3/file31_ext.dat
/new_dir/subdir3/file32_ext.dat
/new_dir/subdir3/file33_ext.dat

ด้วยเหตุนี้คำสั่งควรสร้าง dir ย่อยเหล่านั้นด้วยชื่อที่เกี่ยวข้อง ฉันรู้ว่ามีบรรทัดเช่นนี้:

find . -name "*_ext.dat" -print0 | xargs -0 rm -rf

ฉันสามารถลบไฟล์เหล่านั้นทั้งหมด แต่ฉันไม่รู้วิธีแก้ไขเพื่อทำสิ่งที่ฉันต้องการ (หรือถ้าเป็นไปได้)


1
บางสิ่งบางอย่างอาจrsync --include=*_ext.dat /main_dir/ /new_dir/จะทำเคล็ดลับ ยังไม่ได้ทดสอบ
Jaap Eldering

คำตอบ:


1

ฉันจะสร้างไดเรกทอรีย่อยก่อนnew_dirโดย

cd main_dir
for i in *; do mkdir "../new_dir/$i"; done
cd ..

แล้วคุณสามารถใช้bash's forคำสั่งอีกครั้งพร้อมกับการขยายตัวของรูปแบบที่จะทำสิ่งที่คุณต้องการได้อย่างรวดเร็ว:

for i in main_dir/*/*_ext.dat; do cp "$i" "new_dir${i##main_dir}"; done

ใช้ความจริงที่ว่ามีไดเรกทอรีปลายทางอยู่ สุดท้ายหากไม่ได้รับประกันว่าแต่ละอันจะถูกใช้จริงคุณสามารถล้างสิ่งที่ว่างเปล่าในภายหลัง:

cd new_dir
rmdir --ignore-fail-on-non-empty *

ในวงแรกที่คุณคาดหวังว่าในmain_dirนั้นมีไดเรกทอรีเท่านั้น นอกจากนี้คุณยังไม่ได้ใส่เครื่องหมายคำพูดคู่ในทุกรหัสของคุณดังนั้นมันจะไม่ทำงานกับชื่อไฟล์ที่มีช่องว่าง for i in */; do mkdir "../new_dir/$i"; doneรหัสนี้จะมีประสิทธิภาพมากขึ้น: --- ส่วนสุดท้ายของรหัสจะไม่ลบไดเรกทอรีที่มีไดเรกทอรีว่างเปล่า สำหรับสิ่งที่คุณสามารถใช้find: คุณจะลบไดเรกทอรีว่างที่ซ้อนกันโดยใช้สคริปต์ Bash บน Linux ได้อย่างไร
pabouk

@pabouk แน่นอนมันจะ (บางทีคุณไม่ได้สังเกตเห็นcdก่อนหน้านี้?) หน้าคนrmdirพูดว่า: "DESCRIPTION ... ลบ DIRECTORY (IES) หากพวกเขาว่างเปล่า" ตัวเลือก--ignore-fail-on-non-emptyจะยกเลิกการเตือนว่าไดเรกทอรีที่ไม่ว่างถูกปล่อยออกมา ยิ่งไปกว่านั้นฉันลองในระบบของฉันก่อนโพสต์
วี

นอกจากนี้โครงสร้างไดเรกทอรีที่คำสั่งของฉันคาดว่าเห็นด้วยอย่างสมบูรณ์กับวิธีที่ OP แนะนำรวมถึงตัวอย่างที่ชัดเจนของเขา แน่นอนคำสั่งจะแตกต่างกันถ้าโครงสร้างเป็น
Vee

ขอบคุณสำหรับความคิดเห็นเกี่ยวกับช่องว่าง แก้ไขแล้ว.
Vee

ยินดี. คุณพูดเกินจริงด้วยเครื่องหมายคำพูดคู่ คำสั่งสุดท้ายจะไม่ทำสิ่งที่คุณต้องการ --- วงแรก:มันไม่ดีกว่าที่จะเพิ่มเดี่ยว/เพื่อให้รหัสเป็นสากลมากขึ้นและใช้งานได้มากกว่ากรณี? --- คำสั่งสุดท้ายไม่ทำงาน: mkdir a ; cd a ; mkdir -p a/b/c d/e/f g/h/i ; ls ; rmdir --ignore-fail-on-non-empty * ; ls--- ผลลัพธ์:a d g a d g
pabouk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.