ฉันมีชื่อโฟลเดอร์/home/user/tempsซึ่งมี 487 โฟลเดอร์ ในแต่ละโฟลเดอร์ฉันมีไฟล์ชื่อ thumb.png
ฉันต้องการคัดลอกไฟล์ทั้งหมดที่ชื่อว่า thumb.png ไปยังโฟลเดอร์แยกต่างหากและเปลี่ยนชื่อไฟล์ตามโฟลเดอร์ที่มาจาก
ฉันมีชื่อโฟลเดอร์/home/user/tempsซึ่งมี 487 โฟลเดอร์ ในแต่ละโฟลเดอร์ฉันมีไฟล์ชื่อ thumb.png
ฉันต้องการคัดลอกไฟล์ทั้งหมดที่ชื่อว่า thumb.png ไปยังโฟลเดอร์แยกต่างหากและเปลี่ยนชื่อไฟล์ตามโฟลเดอร์ที่มาจาก
คำตอบ:
ไปเลย:
for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;แก้ไข:
ภูมิปัญญาที่ยอมรับโดยวิธีการคือการใช้ findสำหรับนี้เป็นความคิดที่ไม่ดี - เพียงแค่การใช้การขยายตัวของเปลือกมีความน่าเชื่อถือมากขึ้น นอกจากนี้สมมติว่าbashแต่ฉันคิดว่ามันเป็นสมมติฐานที่ปลอดภัย :)
แก้ไข 2:
เพื่อความชัดเจนฉันจะทำลายมันลง:
# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do
    # replace 'temps' with 'new_folder' in the path
    # '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
    new_file=${file/temps/new_folder};
    # drop '/thumb' from the path
    # '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
    cp "$file" "${new_file/\/thumb/}";
done;รายละเอียดเกี่ยวกับ${var/Pattern/Replacement}การสร้างที่สามารถพบได้ที่นี่
คำพูดในcpบรรทัดมีความสำคัญในการจัดการช่องว่างและการขึ้นบรรทัดใหม่ ฯลฯ ในชื่อไฟล์
new_file/\/thumbคืออะไร?
                    ${VARIABLE/PATTTERN/REPLACEMENT}สร้างมูลค่าVARIABLEแต่ด้วยรูปแบบแทนที่ด้วยข้อความแทนที่ ที่นี่รูปแบบคือ/thumb( /ความต้องการที่จะหลบหนีเพื่อให้มันดูไม่เหมือน${new_file//PATTERN/REPLACEMENT}ซึ่งทำให้เป็นการแทนที่ทั่วโลกแทนที่จะเป็นการแทนที่ครั้งแรกที่เกิดขึ้น) และข้อความการแทนที่นั้นว่างเปล่า
                    /home/user/tempsซึ่งไม่ชัดเจนจากคำถาม หากพวกเขาไม่ได้คุณจะต้องพบ**หรือ
                    สิ่งนี้ใช้ได้กับไดเรกทอรีย่อยที่มีความลึกตามอำเภอใจ:
$ find temps/ -name "thumb.png" | while IFS= read -r NAME; do cp -v "$NAME" "separate/${NAME//\//_}"; done
`temps/thumb.png' -> `separate/temps_thumb.png'
`temps/dir3/thumb.png' -> `separate/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `separate/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `separate/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `separate/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `separate/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `separate/temps_dir2_dir21_thumb.png'ส่วน interessting คือการขยายตัวพารามิเตอร์  ${NAME//\//_}มันต้องใช้เนื้อหาของNAMEและแทนที่ทุกการเกิดขึ้นของด้วย/_
หมายเหตุ: ผลลัพธ์ขึ้นอยู่กับไดเร็กทอรีการทำงานและพารามิเตอร์ path สำหรับ find ฉันเรียกใช้งานคำสั่งจากไดเรกทอรีแม่ของ temps แทนที่cpด้วยechoเป็นการทดสอบ
รหัสผู้ช่วยสั้น:
#!/bin/bash
#
# echo cp "$1" ../tmp/"${1//\//_}" 
#
mv "$1" ../tmp/"${1//\//_}"ลองตั้งชื่อมันว่า 'deslash.sh' และทำให้มันใช้งานได้ โทรไปที่:
find -type f -name thumb.png -exec ./deslash.sh {} ";"    มันจะล้มเหลวหากมีการชนกัน
a/b/thumb.png # and 
a_b/thumb.png แต่นั่นก็หลีกเลี่ยงไม่ได้
ลองสิ่งนี้
mkdir /home/user/thumbs
targDir=/home/user/thumbs
cd /home/user/temps
find . -type d | 
 while IFS="" read -r dir ; do
   if [[ -f "${dir}"/thumb.png ]] ; then
     echo mv -i "${dir}/thumb.png" "${targDir}/${dir}_thumb.png"
   fi
doneแก้ไข
ฉันได้เพิ่มข้อความในกรณีที่ชื่อ dir ของคุณมีตัวอักษรสีขาวฝังอยู่ในนั้น
นอกจากนี้ฉันได้เปลี่ยนแปลงสิ่งนี้ดังนั้นมันจะพิมพ์เฉพาะคำสั่งที่จะดำเนินการ ตรวจสอบเอาต์พุตของสคริปต์เพื่อให้แน่ใจว่าชื่อไฟล์ / พา ธ ทั้งหมดดูเหมาะสม echoเมื่อคุณกำลังตรวจสอบว่ามีปัญหาเกี่ยวกับคำสั่งที่จะดำเนินการไม่เอา
mv -i ./A A/thumb.png ../tmp/.png- ไฟล์ทั้งหมดสิ้นสุดใน ../tmp/.png (../tmp เป็นเป้าหมายของฉัน dir)
                    find -type dและดูผลลัพธ์ ไม่ได้รับไดเรกทอรีทั้งหมดที่คุณคาดหวังหรือไม่ หากเป็นเช่นนั้นโปรดเพิ่มเอาต์พุตบางส่วนเพื่อแสดงปัญหา โชคดี.
                    read dirดำเนินการแยกคำและรับจากไดเรกทอรีa\nba และ b เป็นสองอินสแตนซ์ซึ่งไม่สามารถปิดบังได้
                    ในการคัดลอกคุณต้องการคำสั่งcpและการเปลี่ยนชื่อสำหรับ linux นั้นเหมือนกับการย้ายไฟล์ดังนั้นคุณต้องทำด้วยคำสั่งmv ใน Linux คุณจะต้องระบุเส้นทางทั้งหมดจากแหล่งหากคุณอยู่ในโฟลเดอร์อื่นและไปยังโฟลเดอร์ปลายทางแน่นอน ฉันจะเป็นอย่างนี้เพื่อคัดลอก:
cp /source_path/file /destination_path/หรือเพื่อเปลี่ยนชื่อหรือย้าย
mv /source_path/old_file /destination_path/new_name_file