วิธีสร้างไฟล์ที่ตั้งชื่อตามบรรทัดในไฟล์ข้อความภายใต้ Linux


7

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

คำสั่งใดที่ฉันควรใช้ทำจากบรรทัดคำสั่ง ฉันคิดว่าcat, grepและtouch(และอาจจะxargs?) ควรมีส่วนร่วมในกระบวนการ แต่หลังจากการทดลองไม่กี่ฉันยังคงไม่สามารถหาไวยากรณ์ที่ถูกต้อง

ใครบางคนสามารถสอนฉันเกี่ยวกับเรื่องนี้?

คำตอบ:


10

สมมติว่าคุณมีlist.txtสิ่งนี้:

file 1
file 2
file 3

คุณสามารถบรรลุสิ่งที่คุณต้องการด้วย:

while read FILE; do touch "${FILE} some string"; done < list.txt

ทำไม... < list.txtมากกว่าcat list.txt | ...? ได้รับการวางไข่หลังเป็นcatกระบวนการที่อดีตไม่ได้ แต่ก็ยังมีพฤติกรรมที่คาดการณ์ได้มากขึ้นและชัดเจนยิ่งกว่า ...
Aaron Miller

1
การเปลี่ยนเส้นทางรวมอยู่ใน Bash ไม่จำเป็นต้องใช้catที่นี่ < list.txt while ...ถ้าคุณต้องการคุณสามารถเขียนการเปลี่ยนเส้นทางก่อนที่คำสั่งนี้: คุณสามารถทำอย่างละเอียด"แต่มันก็ยังจะทำงานมากขึ้นคาดการณ์" ?
cYrus

ISTR ประสบปัญหาในอดีตที่จริง< fileหรือ< `command`ไม่ได้ผลิตอะไรในอินพุตมาตรฐานของคำสั่งที่มันมุ่งไปจนถึงจุดที่ฉันเลิกพยายามที่จะให้มันทำงาน - ดังนั้นฉันจึงเริ่มต้นcat file |ในการตอบ . แม้ว่าจะเป็นเมื่อไม่นานมานี้และอาจเป็นได้ว่าฉันไม่รู้ว่ากำลังทำอะไรอยู่ ฉันน่าจะลองอีกครั้ง
Aaron Miller

1
ที่กล่าวว่า< list.txt while read FILE...doneยังคงดูเหมือนผิด ฉันเข้าใจว่าไม่ใช่ แต่ดูเหมือนว่าควรจะเป็น :)
Aaron Miller

8

ดังนั้นคุณจะได้ไฟล์listที่มี:

this
that
the-other

และคุณต้องการสร้างสำหรับแต่ละบรรทัดในไฟล์นั้นไฟล์ที่มีชื่อที่ให้ไว้ในบรรทัดนั้น มันค่อนข้างง่าย - ถ้าหากแต่ละบรรทัดประกอบด้วยเพียงคำเดียว:

cat list | xargs touch --

(การ--บอกtouchไม่ให้พยายามแยกวิเคราะห์อะไรหลังจากเป็นอาร์กิวเมนต์หากไม่มีชื่อไฟล์เช่น-thisนั้นผู้นำ-จะสร้างความสับสนให้กับการคิด 't', 'h', 'i' และ 's' นั้นมีความหมายเหมือน การขัดแย้งมากกว่าส่วนของชื่อไฟล์ที่แท้จริงที่จะสัมผัส)

นั่นเป็นกรณีง่าย ๆ ที่ได้รับการดูแล แต่ไม่ใช่สิ่งที่คุณถาม หากคุณต้องการให้ชื่อไฟล์มีข้อความเกินกว่าที่ระบุไว้ในบรรทัดlistสิ่งต่าง ๆ จะมีความซับซ้อนมากขึ้น xargs ไม่สามารถทำการแก้ไขแบบนั้นได้ แต่คุณต้องการสิ่งต่อไปนี้ (ซึ่งต้องการให้เชลล์ของคุณเป็นbashเช่นเดียวกับมาตรฐานในระบบส่วนใหญ่):

for file in `cat list`; do touch -- $file-customtext; done

ระวังว่าวิธีนี้จะใช้ได้เฉพาะเมื่อแต่ละบรรทัดประกอบด้วยคำเดียวเท่านั้น ในคำสั่งนี้$fileจะถูกแทนที่ด้วยชื่อไฟล์ที่ระบุในบรรทัดที่กำหนดในlist; ทุกอย่างรอบตัวมันถูกถ่ายอย่างแท้จริงดังนั้นคำสั่งนี้ที่มีlistเนื้อหาด้านบนจะสร้างไฟล์ต่อไปนี้

this-customtext
that-customtext
the-other-customtext

คุณสามารถแทนที่ '-customtext' ด้วยสิ่งที่คุณต้องการแน่นอนและคุณสามารถมีคำนำหน้าเช่นเดียวกับคำต่อท้าย; do touch -- some-$file-textตัวอย่างเช่นถ้าคุณมีมันจะทำงานได้ดีและส่งผลให้ไฟล์ชื่อsome-this-text& c

ตอนนี้สมมติว่าเนื้อหาของlistไม่ง่ายนัก - โดยเฉพาะพวกมันมีช่องว่างอักขระที่ไม่ใช่คำหรือสิ่งอื่น ๆ ที่เชลล์ไม่สามารถตีความได้อย่างถูกต้อง หากคุณถามคนสามคนถึงสิ่งที่พวกเขาต้องการแนะนำในกรณีนี้คุณน่าจะได้รับคำตอบห้าข้อ ฉันเป็นแฮ็กเกอร์ Perl ดังนั้นคำตอบของฉันคือ Perl โดยเฉพาะสมมติlistว่ามี:

This is the first line
of three (three?) lines
in the list file.

วิธีที่ฉันจะทำคือ:

cat list | perl -ne'chomp; system(qq|touch -- "custom $_ text"|)'

ซึ่งสร้างไฟล์ผลลัพธ์:

custom This is the first line text
custom of three (three?) lines text
custom in the list file. text

ข้อความที่กำหนดเองในกรณีนี้อาจเป็นสิ่งที่คุณต้องการเว้นวรรคและทั้งหมดตราบใดที่มันไม่มี"(ซึ่งจะทำให้สับสนtouch) หรือ'(ซึ่งจะทำให้สับสนperl); ในคำสั่ง Perl $_หมายถึงเนื้อหาของบรรทัดที่listกำหนดและข้อความที่กำหนดเองเป็นของก่อนหรือหลัง แต่ภายในเครื่องหมายคำพูดคู่ (ข้อความที่กำหนดเองนอกเครื่องหมายคำพูดคู่จะถูกพิจารณาtouchว่าเป็นชื่อไฟล์แยกซึ่งจะถูกสร้างขึ้นอย่างแท้จริงเว้นแต่จะมีสิ่งที่จะทำให้เกิดtouchข้อผิดพลาด)


1
Nope! เห็นได้ชัดว่าเมื่อคุณforข้ามเส้นในbashก็จะใช้เวลาว่างใด ๆ \nเป็นตัวคั่นบรรทัดแทนเพียง ฉันรู้ว่าbashมันแปลกและพิถีพิถัน แต่ ... ในทุกกรณีฉันได้อัปเดตคำตอบเพื่อจัดการกรณีนี้ด้วย Perl บรรทัดคำสั่งเล็กน้อย
Aaron Miller

1
นอกจากนี้เพียงแค่ FYI การใส่สตริงใน backticks ( `) สถานที่ส่วนใหญ่ที่คุณสามารถทำได้จะทำให้สตริงนั้นถูกใช้เป็นคำสั่งที่ผลลัพธ์ถูกสอดเข้าไปแทนที่เช่นเดียวกับการforสร้างคำตอบของฉัน
Aaron Miller

1
โปรดอ่าน: ทำไมคุณไม่ควรอ่านบรรทัดด้วย - ไม่จำเป็นต้องมีperlวิธีแก้ไขหรือใช้งานcatจริง ๆ คุณเพียงแค่ใช้while readโครงสร้างแทน ทุบตีไม่ได้ถูกจู้จี้จุกจิกมันก็ถือว่าช่องว่างเป็นตัวคั่นอาร์กิวเมนต์
slhck

1
Bash ใช้เวลาสักครู่ในการทำความคุ้นเคย แต่มักจะมีวิธีมาตรฐานในการทำสิ่งต่าง ๆ ที่คุณจะต้องเรียนรู้ครั้งเดียวจากนั้นนำไปใช้ได้ทุกที่ :) คำถามที่พบบ่อยเกี่ยวกับ Bashครอบคลุมเกือบทุกกรณี
slhck

1
@Sekhemty ฉันอยากจะแนะนำให้ใช้วิธีแก้ปัญหาแบบนี้จริงๆ ทุบตีสามารถรักษาไฟล์ที่มีช่องว่างในชื่อของพวกเขาได้ดีคุณเพียงแค่ต้องใช้คำสั่งที่เหมาะสม (ดูคำตอบของ cYrus ด้านล่าง) หลายคนมีปัญหากับ Bash ต้นกำเนิดจากคำสั่ง "ผิด" พวกเขาพบว่าforวนซ้ำไปซ้ำในไฟล์ ใช้งานได้ดีกับหลายกรณี แต่ไม่คาดคิดสำหรับผู้อื่น
slhck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.