ลบพา ธ จากเอาต์พุตคำสั่ง find


29

ฉันมีสคริปต์ทุบตีสำหรับการปรับใช้รหัสจากสภาพแวดล้อมเบต้ากับสภาพแวดล้อมการผลิต แต่ปัจจุบันฉันต้องเพิ่มรายการของไฟล์ลงในไฟล์ txt manaully และบางครั้งฉันก็พลาดบางอย่าง โดยพื้นฐานแล้วสคริปต์การปรับใช้ของฉัน cat / ลูปคัดลอกไฟล์ทับ (ส่งออก / นำเข้า db เช่นกัน แต่ไม่เกี่ยวข้อง .. ฮ่า ๆ )

อย่างไรก็ตามฉันต้องการใช้findคำสั่งเพื่อสร้างรายการไฟล์ที่แก้ไขในช่วง 14 วันที่ผ่านมา ปัญหาคือฉันจำเป็นต้องตัดพา ธ ออก./เพื่อให้สคริปต์การปรับใช้ทำงานได้

นี่คือตัวอย่างของการใช้คำสั่ง find:

หา -type f -mtime -14> deploy.txt

นี่คือบรรทัดที่แมวdeploy.txtในสคริปต์การปรับใช้ของฉัน:

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

มีความคิดว่าจะทำสิ่งนี้ให้สำเร็จได้อย่างไรโดยใช้ bash scripting?

ขอบคุณ!


3
มีเหตุผลที่คุณไม่สามารถใช้ rsync เพื่อทำสิ่งนี้ได้หรือไม่? ดูเหมือนว่าคุณกำลังพยายามสร้างล้อและทำให้มันเป็นรูปสามเหลี่ยม
ThatGraemeGuy

จุดที่ถูกต้องอย่างไรก็ตามก่อนการปรับใช้ deploy.txt จะได้รับการตรวจสอบและสิ่งที่จำเป็นต้องแก้ไขจะถูกลบออก
Mikey1980

1
อาจเรียกใช้ rsync ใน--dry-runโหมดและส่งออกไปยังไฟล์เพื่อการตรวจสอบ?
Zoredache

คำตอบ:


36

คุณสามารถใช้-printfตัวเลือกบรรทัดคำสั่งด้วย%fเพื่อพิมพ์เฉพาะชื่อไฟล์โดยไม่มีข้อมูลไดเรกทอรีใด ๆ

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

หรือคุณสามารถใช้ sed เพื่อลบ. /

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt

/.ผมเชื่อว่าคุณมีที่จะหลบหนี
EEAA

5
ไม่ใช่เมื่อคุณใช้|เป็นตัวคั่น
user9517 รองรับ GoFundMonica

3
การใช้จะเปลื้องผ้าไดเรกทอรีทั้งหมดไม่เพียง%f ./สิ่งนี้จะทำลายสคริปต์การปรับใช้ของเขาหากไฟล์ใด ๆ ที่ส่งคืนโดยfindอยู่ในไดเรกทอรีย่อย
James Sneeringer

2
@Iain คุณจำเป็นต้องหลบหนี.แม้ว่า และอาจดีที่สุดในการใช้จุดยึดเริ่มต้น:s|^\./||
James O'Gorman

12
ใช้แทน%P %fนี่เพิ่งตัดพา ธ ที่กำหนดในบรรทัดคำสั่ง
TrueY

11

./ควรจะไม่เป็นอันตราย โปรแกรมส่วนใหญ่จะปฏิบัติต่อ/foo/barและ/foo/./barเทียบเท่า ฉันรู้ว่ามันดูไม่ดีนัก แต่ขึ้นอยู่กับสิ่งที่คุณโพสต์ฉันไม่เห็นสาเหตุที่ทำให้สคริปต์ของคุณล้มเหลว

หากคุณต้องการถอดออกจริงๆsedอาจเป็นวิธีที่สะอาดที่สุด:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

หากคุณอยู่ในระบบที่มี GNU พบ (เช่นระบบ Linux ส่วนใหญ่) คุณสามารถทำได้ในนัดเดียวด้วยfind -printf:

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

%Pผลตอบแทนเส้นทางที่สมบูรณ์ของแต่ละไฟล์พบลบเส้นทางที่ระบุในบรรทัดคำสั่งและรวมถึงเฉือนแรก สิ่งนี้จะเก็บรักษาไดเรกทอรีย่อยใด ๆ ไว้ในโครงสร้างไดเรกทอรีของคุณ


1
./คำนำหน้าเป็นจริงคุณลักษณะ; หากไม่มีมันการไพพ์เอาต์พุตไปยังคำสั่งอื่นจะทำงานไม่ถูกต้องเช่นสำหรับชื่อไฟล์ที่ขึ้นต้นด้วยเส้นประ
tripleee

1
@tripleee - ฉันเข้าใจยูทิลิตี้ของมัน แต่ OP ถามวิธีถอดมันออกโดยเฉพาะเพราะมันทำให้เกิดปัญหากับสคริปต์การปรับใช้ของเขา แน่นอนว่าอาจมีวิธีที่ดีกว่าในการทำสิ่งที่เขาต้องทำ แต่นั่นเป็นหลุมกระต่ายที่อยู่นอกเหนือขอบเขตของสิ่งที่ถูกถาม
James Sneeringer

7

ทำไมคุณต้องถอดสาย./? มันถูกต้องที่จะมีในเส้นทาง ดังนั้น

cp -i dir1/./somefile dir2/./somefile

ไม่เป็นไร!

แต่ถ้าคุณต้องการตัดชื่อไดเรกทอรีใน find คุณสามารถใช้%Pหาเรื่อง-printfได้

ผู้ชายพบ (1)พูดว่า:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

ตัวอย่าง

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

ระวังบรรทัดว่างแรก! หากคุณต้องการหลีกเลี่ยงการใช้งาน-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit

3

คุณมีตัวเลือกน้อย คุณสามารถใช้-printfตัวเลือกในการค้นหาเพียงพิมพ์ชื่อไฟล์หรือคุณอาจจะใช้เครื่องมือเช่น sed ./เพียงแค่ดึงออก

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'

คุณช่วยยกตัวอย่างการใช้งานให้ฉันได้ไหม ขออภัย linux ไม่ใช่
ป้อมปราการ

2
ดูอีกครั้งมีตัวอย่าง
Zoredache

เห็นด้วย - ลองเลยคุณจะไม่เจ็บอะไรเลยที่ใช้การผสมผสานระหว่างการค้นหาและการนอน
EEAA

3

โซลูชัน "find -printf" จะไม่ทำงานบน FreeBSD เนื่องจากการค้นหาไม่มีตัวเลือกดังกล่าว ในกรณีนี้ AWK สามารถช่วยคุณได้ มันส่งคืนนามสกุล ($ NF) ดังนั้นจึงสามารถทำงานได้ในทุกระดับความลึก

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

PS: นำมาจากหนังสือ D.Tansley "การเขียนโปรแกรม Linux และ Unix shell"


2

วิธีแก้ปัญหาอย่างรวดเร็วหากฉันเข้าใจคำถามถูกต้องใช้cutกับผลลัพธ์ของfindคำสั่ง:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

สิ่งนี้จะตัดอักขระตัวแรกกับตัวอักษรจากแต่ละบรรทัดของผลลัพธ์ (ในกรณีของคุณ./) อาจไม่ใช่ทางออกที่ดีที่สุด แต่ใช้ได้ในสถานการณ์ของคุณ



1

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

ข้อเสนอแนะของฉันจะใช้การขยายพารามิเตอร์ของ shell เพื่อตัดอักขระจากชื่อไฟล์แต่ละชื่อ:

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

หากคุณชอบท่อจริงๆคุณสามารถใช้ตัวคั่น "ปลอดภัย" เช่นค่า null ด้วย xargs เพื่อรับชื่อไฟล์แต่ละชื่อ:

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

โปรดจำไว้ว่าผลลัพธ์ของสิ่งนี้ไม่ใช่ตัวคั่นที่เป็นโมฆะดังนั้นในขณะที่มันอาจจะเพียงพอสำหรับการตรวจลูกตาไม่มีวิธีการแก้ปัญหาใด ๆ ที่สร้างไฟล์ deploy.txt ที่ปลอดภัยสำหรับการใช้งานอัตโนมัติเว้นแต่คุณจะมั่นใจมากเกี่ยวกับแหล่งที่มาของคุณ ชื่อไฟล์

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