ฉันมีชื่อโฟลเดอร์/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\nb
a และ b เป็นสองอินสแตนซ์ซึ่งไม่สามารถปิดบังได้
ในการคัดลอกคุณต้องการคำสั่งcpและการเปลี่ยนชื่อสำหรับ linux นั้นเหมือนกับการย้ายไฟล์ดังนั้นคุณต้องทำด้วยคำสั่งmv ใน Linux คุณจะต้องระบุเส้นทางทั้งหมดจากแหล่งหากคุณอยู่ในโฟลเดอร์อื่นและไปยังโฟลเดอร์ปลายทางแน่นอน ฉันจะเป็นอย่างนี้เพื่อคัดลอก:
cp /source_path/file /destination_path/
หรือเพื่อเปลี่ยนชื่อหรือย้าย
mv /source_path/old_file /destination_path/new_name_file