คุณสามารถทำได้ง่ายพอโดยใช้ตัวเลือก globstar ของ bash (จาก ผู้ชายทุบตี):
โกลบอลสตาร์
ถ้ากำหนดรูปแบบ ** ใช้ในบริบทการขยายชื่อพาธจะตรงกับไฟล์ทั้งหมดและไดเร็กทอรีและไดเร็กทอรีย่อยเป็นศูนย์หรือมากกว่า ถ้าแบบตามด้วยก /เฉพาะไดเร็กทอรีและไดเร็กทอรีย่อยเท่านั้นที่ตรงกัน
เนื่องจากเราสามารถใช้ ** ในการค้นหาไฟล์ เราเพียงแค่กำหนดชื่อใหม่โดยรวมถึงชื่อไดเร็กทอรีดั้งเดิมและการเปลี่ยนแปลง . ถึง _:
สำหรับไฟล์ใน **/*.txt; ทำ
newName=$(sed 's|[/.]|_|g' <<<"$file" | sed 's/_txt$/.txt/')
cp -- "$file" foo/"$newName"
เสร็จแล้ว
คำอธิบาย
สำหรับไฟล์ใน **/*.txt; ทำ: ค้นหาไฟล์ทั้งหมด (และไดเร็กทอรี หากเกี่ยวข้อง) ในไดเร็กทอรีปัจจุบันที่มีชื่อลงท้ายด้วย *.txt.
newName=$(sed 's|[/.]|_|g' <<<"$file" | sed 's/_txt$/.txt/') : ใช้ เสด เพื่อแปลงทั้งหมด / และ . ถึง _ ในชื่อไฟล์. โปรดทราบว่า $ไฟล์ ที่นี่รวมถึงเส้นทางด้วยดังนั้นมันจะเป็นเช่น case1/0.25/case1.txt และนั่นกลายเป็น case1_0_25_case1_txt. จากนั้นเราจะผ่านเอาต์พุตของอันแรก เสด เป็นครั้งที่สองซึ่งแปลง _txt (หากพบว่าอยู่ท้ายบรรทัด) ถึง .txtให้เรา ``case1_0_25_case1.txt. ผลลัพธ์สุดท้ายจะถูกบันทึกไว้ในตัวแปร $newName`.
cp -- "$file" foo/"$newName": ตอนนี้เราคัดลอกไฟล์ไปยังไดเร็กทอรี ฟู/ และด้วยชื่อใหม่ เดอะ -- ไม่จำเป็นจริงๆ ที่นี่ แต่ให้แน่ใจว่าแนวทางนี้จะใช้ได้กับชื่อไฟล์ใดๆ รวมถึงชื่อที่ขึ้นต้นด้วย a -.
ฉันสร้างโครงสร้างโฟลเดอร์ที่คุณแสดงในคำถามของคุณใหม่ เรียกใช้คำสั่งด้านบนและได้รับ:
$ ต้นไม้
.
âââ กรณีที่ 1
€ 0.25
ââ â ââ â âââ case1.txt
â âââ 0.30
ââ â ââ â âââ case1.txt
€ 0.35
ââ â ââ â âââ case1.txt
€ 0.45
â âââ case1.txt
âââ กรณีที่ 2
€ 0.25
ââ â ââ â âââ case2.txt
â âââ 0.30
ââ â ââ â âââ case2.txt
€ 0.35
ââ â ââ â âââ case2.txt
€ 0.45
â âââ case2.txt
âââ ฟู
âââ case1_0_25_case1.txt
âââ case1_0_30_case1.txt
âââ case1_0_35_case1.txt
âââ case1_0_45_case1.txt
âââ case2_0_25_case2.txt
âââ case2_0_30_case2.txt
âââ case2_0_35_case2.txt
âââ case2_0_45_case2.txt
11 ไดเร็กทอรี 16 ไฟล์