ฉันจะเพิ่มข้อความไปยังจุดเริ่มต้นของไฟล์ใน Bash ได้อย่างไร


285

สวัสดีฉันต้องการที่จะเพิ่มข้อความลงในไฟล์ ตัวอย่างเช่นฉันต้องการเพิ่มงานไปยังจุดเริ่มต้นของไฟล์ todo.txt ฉันรู้echo 'task goes here' >> todo.txtแต่เพิ่มบรรทัดไปยังจุดสิ้นสุดของไฟล์ (ไม่ใช่สิ่งที่ฉันต้องการ)


2
หากไม่มีวิธีที่มีประสิทธิภาพในการทำเช่นนั้นสำหรับไฟล์ขนาดใหญ่: unix.stackexchange.com/questions/87772/ …
Ciro Santilli 新疆改造中心中心法轮功六四事件

@ คุณจะดูที่วิธีการนี้superuser.com/a/1352628/11116
Evan Carroll

คำตอบ:


374
echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

หรือ

sed -i '1s/^/task goes here\n/' todo.txt

หรือ

sed -i '1itask goes here' todo.txt

4
คนแรกใช้งานได้ดี! คุณจะอธิบายถึงเหตุผลหรือไม่ ฉันไม่แน่ใจว่าจะตีความไวยากรณ์อย่างไร
user479534

44
@ user8347: Pipe ( |) ข้อความ ( echo '...') catซึ่งใช้-(อินพุตมาตรฐาน) เป็นไฟล์แรกและไฟล์todo.txtที่สอง catเชื่อมต่อหลายไฟล์ ส่งเอาท์พุท ( >) tempเพื่อไฟล์ชื่อ หากไม่มีข้อผิดพลาด ( &&) จากcatนั้นเปลี่ยนชื่อ ( mv) tempไฟล์กลับไปเป็นไฟล์ดั้งเดิม ( todo.txt)
Dennis Williamson

1
@itaifrenkel: ฉันต้องดูว่าคุณทำอะไร แต่ถ้าcatได้รับแบ็กสแลชตามตัวอักษร n มันจะไม่แปลงเป็นบรรทัดใหม่ อย่างอื่นจะต้องทำอย่างนั้น แทนที่จะcatลองใช้ piping hexdump -Cเพื่อดูว่าคุณกำลังส่งแบ็กสแลชและ n หรือว่าเป็นบรรทัดใหม่ คุณสามารถลองcat -eแสดงการจบบรรทัดได้
Dennis Williamson

1
การใช้ 2 และ 3 (3 ดูเหมือนง่ายสำหรับฉัน) ช่วยให้คุณสามารถเพิ่มข้อความลงในไฟล์หลายไฟล์พร้อมกัน
เฟลิกซ์

4
@Kira ที่: 1วิธีการทำคำสั่งต่อไปเท่านั้นในบรรทัดหนึ่งของไฟล์และiคำสั่งแทรก ดูในหน้า man ภายใต้ส่วน "Addresses" และในส่วน "Zero- หรือ One-address command"
Dennis Williamson

73

ตัวเลือกที่ง่ายกว่าในความคิดของฉันคือ:

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

สิ่งนี้ได้ผลเพราะคำสั่งด้านในของ$(...)ถูกดำเนินการก่อนที่จะtodo.txtถูกเขียนทับด้วย> todo.txt

ในขณะที่คำตอบอื่น ๆ ใช้งานได้ดีฉันพบว่าจดจำได้ง่ายกว่านี้เพราะฉันใช้เสียงสะท้อนและแมวทุกวัน

แก้ไข:วิธีนี้เป็นความคิดที่ดีมากหากมีเครื่องหมายแบ็กสแลชใด ๆ อยู่todo.txtเนื่องจากต้องขอบคุณการ-eสะท้อนธงจะตีความพวกเขา อีกวิธีที่ง่ายกว่าในการรับบรรทัดใหม่ในสตริงคำนำหน้าคือ ...

echo "task goes here
$(cat todo.txt)" > todo.txt

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

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

นอกจากนี้หากคุณสนใจว่าจะเพิ่มการขึ้นบรรทัดใหม่todo.txtหรือไม่อย่าใช้สิ่งเหล่านี้ ดียกเว้นคนที่สองถึงครั้งสุดท้าย ที่ไม่ยุ่งกับจุดจบ


1
ฉันไม่ได้รับ $ (... ) เลย
SCL

2
ที่อาจทำงานได้ดีขึ้น (หรือเลย) ด้วยเครื่องหมายคำพูดคู่แทนเดี่ยว…
ℝaphink

5
จะไม่-eแปลงลำดับ escape ใน todo.txt ด้วยหรือไม่
mk12

2
วิธีแก้ปัญหาให้ผลตอบแทน -> cat: <ชื่อไฟล์ปลายทาง>: ไฟล์อินพุตเป็นไฟล์เอาต์พุต ...
นี่

printf จะสอดคล้องกันมากขึ้นในทุกแพลตฟอร์มและโดยทั่วไปแล้วควรทำงานได้ราบรื่นกว่า echo -e
Peter Berg

28

moreutilsมีเครื่องมือที่ดีที่เรียกว่าsponge:

echo "task goes here" | cat - todo.txt | sponge todo.txt

มันจะ "ดูดซับ" STDIN จากนั้นเขียนไปยังไฟล์ซึ่งหมายความว่าคุณไม่ต้องกังวลกับไฟล์ชั่วคราวและย้ายไปมา

คุณจะได้รับmoreutilsมีหลาย Linux distros ผ่านapt-get install moreutilsหรือบน OS X โดยใช้Homebrewbrew install moreutilsด้วย


ฉันจะไปเพื่อ(echo 'ble'; cat todo.txt):-)
Ciro Santilli 新疆改造中心法轮功六四事件


5

คุณสามารถสร้างไฟล์ใหม่ชั่วคราว

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

นอกจากนี้คุณยังอาจใช้หรือsed awkแต่โดยทั่วไปสิ่งเดียวกันก็เกิดขึ้น


1
สมมติว่าคุณออกจากพื้นที่ดิสก์เพื่อให้new_todo.txtเขียนได้เพียงบางส่วนเท่านั้น วิธีการแก้ปัญหาของคุณดูเหมือนจะสูญเสียไฟล์ต้นฉบับ
NPE

ใครมีพื้นที่ดิสก์เหลือน้อย ;-) มันเป็นเพียงตัวอย่างง่ายๆ
Keith

2
@Keith มีคนกำลังทำงานกับ VM ซึ่งไม่ได้คาดหวังว่าจะต้องใช้ไดรฟ์เสมือนขนาดใหญ่เป็นพิเศษ หรือใครบางคนกำลังย้ายไฟล์ขนาดใหญ่ ไม่ว่าในกรณีใดอาร์กิวเมนต์ที่แท้จริงคือสิ่งนี้การอนุญาตไดเรกทอรี หากคุณไม่ได้รับอนุญาตให้สร้างไฟล์ใหม่ในไดเรกทอรีที่กำหนดคำสั่งเดียวที่จะสำเร็จในสคริปต์ของคุณก็คือrmไฟล์ต้นฉบับ
คู่ปรับ Shot

3

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

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

เป็นไปไม่ได้ที่จะเพิ่มบรรทัดไปยังจุดเริ่มต้นของไฟล์โดยไม่ต้องเขียนไฟล์ทั้งหมด


เพื่อถามคำถามที่ชัดเจน: ขีด จำกัด อักขระของตัวแปรเชลล์อยู่ที่ไหน
nixda

เท่าที่ฉันทราบมันถูก จำกัด ด้วยจำนวนหน่วยความจำที่มี ฉันเติมตัวแปรลงในหน่วยความจำได้ดีกว่า 100MB แล้ว text=$(cat file). ระวังการใช้ข้อความเพียงอย่างเดียวเนื่องจากตัวแปรเชลล์ไม่ได้ทำความสะอาดแบบไบนารี่mywiki.wooledge.org/BashFAQ/058
Rucent88

2

คุณไม่สามารถแทรกเนื้อหาที่จุดเริ่มต้นของไฟล์ สิ่งเดียวที่คุณสามารถทำได้คือแทนที่เนื้อหาที่มีอยู่หรือผนวกไบต์หลังจากสิ้นสุดไฟล์ปัจจุบัน

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

ระวังอย่าให้ข้อมูลสูญหายโดยเก็บไฟล์ต้นฉบับไว้ในขณะที่สร้างไฟล์ใหม่หากระบบไฟล์เต็มในระหว่างกระบวนการ เช่น:

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

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

นี่เป็นการยากที่จะแยกวิเคราะห์เป็น <... > ดูเหมือนว่าวงเล็บซึ่งฉันคิดว่าพวกเขาไม่ได้ ช่องว่างระหว่าง <และ (อาจจะช่วยได้บ้าง)
dumbledad

มันไม่ทำงานสำหรับฉัน echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'ใช้งานได้ แต่cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'ให้ข้อผิดพลาด "echo: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว"
dumbledad

@dumbledad คุณคิดมากเกินไปคำตอบของฉัน ไม่มีอะไรให้คุณแยกวิเคราะห์ได้ ช่องว่างระหว่าง<และ(จะทำลายไวยากรณ์ ลองcat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
jlliagre


0

GitBash + Windows10 + หลายบรรทัด :

นี่เป็นรุ่นที่ช่วยให้คุณใช้สตริงหลายคู่สาย

##############################################
## This section for demo purpose only,      ##
## So you can save entire file as           ##
## whatever.sh and run it.                  ##
##                                          ##
##############################################
> MY_TARGET_FILE.txt ##Make Or Clear File
echo "[STARTER_CONTENT]" >> MY_TARGET_FILE.txt
##############################################

## Below is main code:

##################################################
TARGET_FILE_VARIABLE="MY_TARGET_FILE.txt"
ADD_TO_HEAD_VARIABLE=$(cat << "HEREDOC_HEAD_TEXT"
//|  +-------------------------------------+   |//
//|  |                                     |   |//
//|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
//|  |                                     |   |//
//|  +-------------------------------------+   |//
HEREDOC_HEAD_TEXT
)
##################################################
TAR=$TARGET_FILE_VARIABLE                       ##
TEX=$ADD_TO_HEAD_VARIABLE                       ##
echo "$TEX" | cat - $TAR > TEMP && mv TEMP $TAR ##
##################################################

## Expected contents of MY_TARGET_FILE.txt :
## //|  +-------------------------------------+   |//
## //|  |                                     |   |//
## //|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
## //|  |                                     |   |//
## //|  +-------------------------------------+   |//
## [STARTER_CONTENT]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.