ฉันจะใช้ find เพื่อคัดลอกไฟล์ที่พบทั้งหมดไปยังชื่อใหม่ในไดเรกทอรีเดียวกันได้อย่างไร


4

ฉันมีคำสั่งง่ายๆที่เกือบจะเป็นสิ่งที่ฉันต้องการ ต่อไปนี้จะค้นหาไฟล์ทั้งหมดที่มีคำต่อท้ายเป็น '_compressed.swf' และคัดลอกแต่ละไฟล์ลงในไดเรกทอรีเดียวกันโดยใช้ '.bak2' ต่อท้าย:

ค้นหา '../content' -name '* _compressed.swf' -print0 | xargs -0 -I {} cp {} {} .bak2

ผลลัพธ์
ใน: /content/somefile_compressed.swf
Out: /content/somefile_compressed.swf.bak2

อย่างไรก็ตามฉันต้องแทนที่ '_compressed.swf' ด้วย '_content.swf' ฉันต้องการใช้การค้นหาแทนที่การตั้งค่าสถานะแบบเรียกซ้ำบน cp เพื่อความสอดคล้อง

วัตถุประสงค์
ใน: /content/somefile_compressed.swf
Out: /content/somefile_content.swf


1
โพสต์ข้ามที่นี่: serverfault.com/questions/115880/…
Dennis Williamson

คำตอบ:


4

โซลูชันนี้น่าจะเป็นแบบพกพามากที่สุด:

ค้นหา "../content" -name "* _compressed.swf" -exec sh -c 'cp {} `dirname {}` / `basename {} ที่บีบอัด. swf`content.swf' \;

นอกจากนี้ยังมีสคริปต์rename.pl ที่มีชื่อเสียงซึ่งกระจายด้วย Perl และคำสั่งเปลี่ยนชื่อซึ่งอาจทำให้ง่ายขึ้นเล็กน้อย สิ่งเหล่านี้ไม่สามารถใช้ได้กับการแจกแจงทั้งหมดคำสั่งเหล่านี้ส่วนใหญ่


ด้านบนจะย้ายไฟล์จากตำแหน่งปัจจุบันไปยังตำแหน่งของสคริปต์และเพิ่มส่วนต่อท้าย 'content.swf' การเปลี่ยน mv ด้วย cp ทำให้ฉันเข้ามาใกล้ แต่ฉันยังต้องการแทนที่ข้อความในชื่อแทนที่จะผนวก ฉันใกล้ชิดโดยใช้ sed แต่ยังคงเรียนรู้
Michael Prescott

@Michael คุณพูดถูก! ขออภัย ฉันเพิ่งทดสอบในไดเรกทอรีปัจจุบันเท่านั้นดังนั้นทำไมจึงใช้งานได้สำหรับฉัน ฉันคงมัน :)
จอห์น T

เฮ้ขอบคุณจอห์น ฉันชอบมัน. เรื่องนี้เป็นเรื่องใหม่สำหรับฉัน ฉันเข้าใจการใช้งาน find, -exec, sh, dirname {}, basename {} แต่ฉันสับสนเล็กน้อยเกี่ยวกับการใช้งานแบบรวม sh -c '' แปลงสตริงเป็นคำสั่งและรันคำสั่งใช่ไหม mv {} ขยายเป็นหนึ่งในผลลัพธ์การค้นหา "mv ../content/file1of20_compressed.swf ????????" มันเป็นส่วนที่สองของสิ่งที่ฉันยังไม่เข้าใจ อะไรเป็นสาเหตุให้บีบอัดไฟล์. swf ถูกแทนที่ด้วย content.swf? ในโซลูชันของฉันคุณสามารถเห็นฉันเพิ่งเรียนรู้วิธีใช้ sed
Michael Prescott

2
@Michael สิ่งที่เกิดขึ้นคือไฟล์กำลังถูกย้ายด้วยชื่อใหม่ หาก{}มี/etc/somefile_compressed.swf, dirname ใช้เวลา/etcและจะทำให้คุณมีbasename {} compressed.swf somefile_ตอนนี้คุณใส่ทั้ง 2 ร่วมกับเฉือนฉันเพิ่มที่อยู่ตรงกลาง ( /) /etc/somefile_และคุณมี คุณจะสังเกตเห็นผมเพิ่มไปยังจุดสิ้นสุดจึงเสร็จสิ้นคำสั่งเป็นcontent.swf /etc/somefile_content.swfHTH
John T

ฉันจะใช้rename.plถ้าต้องการฟังก์ชั่นmv (ไม่ยากที่จะเพิ่มไปยังระบบใด ๆ ที่มี Perl) แต่ซีพีทำให้สิ่งนี้เป็นสัตว์ร้ายที่แตกต่างกัน คุณต้องปรับแต่งสคริปต์เพื่อทำสำเนาแทนที่จะเปลี่ยนชื่อซึ่งจะใช้งานได้ แต่ใช้ได้มากกว่า @John - หาวิธีแก้ปัญหาที่ดี; มันใหญ่และยาวและน่าเกลียด แต่ดูเหมือนว่ามันจะใช้ได้ (อย่าขอให้ฉันช่วยทดสอบมันเถอะ!) :)
ต้มตุ๋น quixote

1

ฉันแน่ใจว่าทั้งหมดนี้สามารถจัดการได้ในหนึ่งบรรทัด ฉันเข้าใกล้โซลูชันบรรทัดเดียวมากและด้วยความช่วยเหลือบางอย่างใกล้ชิดมากขึ้น แต่ไม่ประสบความสำเร็จ ผลงานดังต่อไปนี้:

#!/bin/bash

# Read all file names into an array
FilesArray=($(find "../content" -name "*_compressed.swf"))

# Get length of an array
FilesIndex=${#FilesArray[@]}


# Use for loop read all directory names
for (( i=0; i<${FilesIndex}; i++ ));
do
    source="${FilesArray[$i]}"
    destination="$(echo "${source}" | sed 's/compressed/content/')"
    cp "${source}" "${destination}"
done

exit 0;

0

ฉันเชื่อว่านี่น่าจะเป็นกลลวงและสามารถพับเก็บได้หนึ่งไลเนอร์ถ้าคุณต้องการจริงๆ;)

find ../content -name '*_compressed.swf' | while read file
do
cp "$file" "${file/_compressed.swf/_content.swf}"
done

การทดแทนรูปแบบการทุบตีทำงานได้ดีในกรณีเหล่านี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.