มีวิธีง่าย ๆ ในการผนวกบรรทัดต่อท้ายไฟล์นอกเหนือจาก `>> 'หรือไม่?


21

เมื่อเร็ว ๆ นี้ฉันกำลังสะท้อนประโยคสั้น ๆ ไปยังtree_holeไฟล์

ฉันใช้echo 'something' >> tree_holeเพื่อทำงานนี้

แต่ฉันก็มักจะกังวลว่าถ้าฉันใส่ผิด>แทนที่จะทำ>>เพราะฉันทำสิ่งนี้บ่อย

ดังนั้นฉันจึงทำ bash func ทั่วโลกของตัวเองใน bashrc:

function th { echo "$1" >> /Users/zen1/zen/pythonstudy/tree_hole; }
export -f th

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

มีผู้ใด?


9
คุณจะไม่ลืมว่าคุณกำลังใช้งานรอบการทำงานทุกครั้งที่คุณป้อน>? เมื่อฉันมีนามแฝงrm="rm -i"และในสภาพแวดล้อมอื่น ๆ เขียนrm *รอคำถามยืนยัน คุณกำลังเรียนรู้นิสัยที่อันตราย!
วอลเตอร์ A

9
@WalterA เอ่อ "วิธีแก้ปัญหา" ของเขาไม่อนุญาตให้พิมพ์> แทนที่จะเป็น >> แต่เขาเรียกใช้ "some_sentence" ซึ่งไม่ทำอะไรเลยหากไม่ได้กำหนดนามแฝง
Random832

1
@ Ranom832 ถูกต้องสำหรับรอบการทำงานของเขา คำเตือนสำหรับ "วิธีแก้ปัญหา" เช่น noclobber เมื่อเขาใช้สิ่งที่คล้าย noclobber ในเปลือกปกติของเขาเขาอาจใช้> เมื่อเขาเป็นรูตชั่วคราวและต้องการผนวกบางสิ่ง
วอลเตอร์ A

7
@ Random832 & WalterA ปกติแล้วฉันจะไม่พูดอะไรเกี่ยวกับเรื่องนี้เมื่อฉันเห็นมัน แต่ฉันคิดว่าบางทีการแจ้งเตือนที่เป็นมิตรอาจจะมีประโยชน์ โปรไฟล์ผู้ใช้ของ Zen ไม่มีรายละเอียดมากนักดังนั้นฉันไม่แน่ใจว่าคุณรู้หรือไม่ว่า"การแก้ปัญหา" ของเขาเป็นรูปแบบที่ถูกต้อง บางทีคุณอาจจะบอกว่า"วิธีแก้ปัญหา" ของพวกเขาหรือOP ของ "วิธีแก้ปัญหา" บางทีคุณอาจรู้จักเซนเป็นการส่วนตัวและคุณก็รู้ว่าเขาถูกต้องในกรณีนี้โปรดให้อภัยเสียง ไม่ใช่เรื่องใหญ่ฉันแค่พูดถึงมันเพราะฉันรู้ว่าฉันจะไม่ได้ชื่นชมมันมากนักถ้าคุณใช้แบบฟอร์มนั้นเพื่อพูดคุยเกี่ยวกับตัวฉัน
Celada

1
@ เซนคุณเขียนว่าคุณกังวลที่จะป้อนผิด> แทนที่จะเป็น >> แผนของ Celada จะช่วยลดความเสี่ยงในสภาพแวดล้อมของคุณและเป็นทางออกที่ดีสำหรับคุณ เมื่อคุณช่วยเหลือเพื่อนบ้านของคุณ (ที่ไม่มี noclobber หรือใช้ ksh) และคุณไม่สนใจอักขระหนึ่งหรือสองตัว> คุณอาจเขียนทับไฟล์ใดไฟล์หนึ่งของเขาโดยไม่ตั้งใจ ดังนั้นทุกครั้งที่คุณได้รับการเตือน noclobber ในสภาพแวดล้อมของคุณขอบคุณพระเจ้าหรือ Celada พูดกับตัวเอง: โอ้โปรดระวังด้วย! เขย่าตัวคุณแล้วรอสองวินาที
วอลเตอร์

คำตอบ:


47

ตั้งค่าnoclobberตัวเลือกของเชลล์:

bash-3.2$ set -o noclobber
bash-3.2$ echo hello >foo
bash-3.2$ echo hello >foo
bash: foo: cannot overwrite existing file
bash-3.2$ 

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

1
@orion คุณจะปิดการใช้งานใน zsh ได้อย่างไร? ฉันจำไม่ได้ว่าปิดใช้งานอย่างชัดเจน แต่การเขียนทับทำงานได้ดีบน zsh ของฉัน
muru

2
มันและsetopt noclobber setopt clobberดูเหมือนว่ามันไม่ได้เป็น "ค่าเริ่มต้น" อย่างแน่นอน แต่ก็ขึ้นอยู่กับไฟล์ปรับแต่งที่มาพร้อมกับ distro ของคุณ
orion

@muru ควรทำงานร่วมกับset [+-]Cเชลล์ที่ทันสมัย
mikeserv

3
@Zen ในทุบตีหรือset +o noclobber set +C
Ruslan

7

หากคุณกังวลว่าไฟล์ของคุณจะได้รับความเสียหายจาก>โอเปอเรเตอร์คุณสามารถเปลี่ยนคุณสมบัติไฟล์ของคุณเพื่อต่อท้ายเท่านั้น:
ในระบบไฟล์ext2 / ext3 / ext4 : chattr +a file.txt
ในระบบไฟล์XFS :echo chattr +a | xfs_io file.txt

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

# This function redirect logs to file or terminal or both!
#@ USAGE: log option data
# To the file     -f file
# To the terminal -t
function log(){
        read -r data       # Read data from pipe line

        [[ -z ${indata} ]] && return 1    # Return 1 if data is null

        # Log to /var/log/messages
        logger -i -t SOFTWARE ${data}

        # While loop for traveling on the arguments
        while [[ ! -z "$*" ]]; do
                case "$1" in
                        -t)
                                # Writting data to the terminal
                                printf "%s\n" "${data}"
                                ;;
                        -f) 
                                # Writting (appending) data to given log file address
                                fileadd=$2
                                printf "%s %s\n" "[$(date +"%D %T")] ${data}" >> ${fileadd}
                                ;;
                        *)
                                ;;
                esac
                shift           # Shifting arguments
        done
}

2
มีปัญหาเล็กน้อยกับสคริปต์นี้ 1) โดยทั่วไปคุณควรใส่เครื่องหมายคำพูดคู่ล้อมรอบการขยายพารามิเตอร์ (สิ่งที่ขึ้นต้นด้วย a $) เพื่อป้องกันการวนซ้ำการแยกคำและปัญหาช่องว่างที่เกี่ยวข้อง แอพพลิเคชั่นShellCheckออนไลน์สามารถตรวจจับสิ่งนี้และปัญหาอื่น ๆ อีกมากมายในสคริปต์ทุบตี ในบันทึกที่เกี่ยวข้อง"$@"เป็นมาก$*ปลอดภัยกว่า
PM 2Ring

3
2) โดยปกติคุณควรเรียกreadคำสั่งพร้อม-rตัวเลือกเพื่อป้องกันแบ็กสแลชใด ๆ ในอินพุตจากการหลีกเลี่ยงอักขระต่อไปนี้ 3) เป็นเรื่องปกติในสคริปต์ทุบตีที่ใช้ตัวพิมพ์เล็กสำหรับชื่อตัวแปรสคริปต์เนื่องจาก ALL UPPER CASE ถูกใช้สำหรับตัวแปรระบบ ดังนั้นหากคุณใช้ตัวพิมพ์ใหญ่สำหรับตัวแปรของคุณเองคุณจะสับสนคนที่อ่านรหัสของคุณและคุณอาจบีบตัวแปรระบบที่คุณต้องการใช้ในสคริปต์ในภายหลัง และถ้าคุณแหล่งสคริปต์มันจะปิดบังตัวแปรสำหรับคำสั่งที่ตามมา
PM 2Ring

3
4) echoเป็นประโยชน์สำหรับการพิมพ์สตริงคงที่ แต่มันสามารถทำสิ่งที่ไม่คาดคิดกับข้อมูลโดยเฉพาะอย่างยิ่งในระบบ GNU มันไกลprintfปลอดภัยในการใช้งาน ดูunix.stackexchange.com/questions/65803/…สำหรับข้อมูลเพิ่มเติมโดยเฉพาะคำตอบของStéphane Chazelas
PM 2Ring

3
@PM 2Ring วันนี้ฉันเรียนรู้หลายสิ่งหลายอย่างจากคุณขอบคุณมาก .. ฉันจะแก้ไขให้เร็วที่สุด
Sepahrad Salour

1
ทำได้ดีมาก Sepahrad!
PM 2Ring

3

ใช้teeกับตัวเลือกผนวก:

foo | tee -a some-file
# or
tee -a some-file <<EOF
blah blah
EOF
# or 
tee -a some-file <<<"blah blah"

5
ความคิดที่ดี +1 แต่ฉันคิดว่าถ้า OP กังวลเกี่ยวกับการลืมตัว>ละครพวกเขาอาจกังวลเกี่ยวกับการลืมตัว-aเลือก!
Celada

@ Celada ฉันคิดว่าเป็นอย่างนั้น (แต่ฉันเดาว่าพิมพ์ผิดพลาดจากการกดแป้นหนึ่งครั้งในชุดการกดแป้นซ้ำหลายครั้งมีแนวโน้มที่จะเกิดขึ้นมากกว่าการลืมตัวเลือก)
muru

0

หลายโปรแกรมที่สามารถเปิดไฟล์สำหรับการเขียนทับสามารถเปิดไฟล์เหล่านี้เพื่อผนวกเช่น gnu dd

dd conv=notrunc oflag=append of=file

มันสามารถอ่าน stdin หรือไฟล์ที่มีชื่อในif= พารามิเตอร์เพิ่ม2>/dev/nullเพื่อระงับการนับไบต์


3
เป็นความคิดที่ดีที่จะทดสอบโค้ดของคุณก่อนโพสต์เป็นคำตอบ ...
PM 2Ring

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

@gilles คุณแสดงข้อมูลผิดที่ลิงค์นั้นเมื่อการนับไม่ถูกระบุ dd จะคัดลอกข้อมูลทั้งหมดที่มีอยู่เช่นเดียวกับ cat
Jasen

-1

ฉันต้องการใช้sed(แม้มีสำเนาสำรอง - ดูส่วนขยายหลังจาก-i):

sed -i.bak '$ a\something' /Users/zen1/zen/pythonstudy/tree_hole

ทำไมฉันถึงไม่แปลกใจเลย ... เจ้าเป็นคนคลั่งไคล้ Costas :) (นั่นเป็นคำชมเชย BTW)
PM 2Ring

@ PM2Ring ใช่ฉันอันตรายมาก! : P
Costas

แน่นอนว่าวิธีการทำงานคือการทำสำเนาไฟล์เพิ่มข้อความใหม่ไปยังจุดสิ้นสุดจากนั้นลบไฟล์ต้นฉบับและเปลี่ยนชื่อสำเนาเป็นชื่อดั้งเดิม สิ่งนี้ (1) ไม่ทำงานหากคุณไม่มีสิทธิ์ในการเขียนไปยังไดเรกทอรี (2) หยุดการเชื่อมโยงและ (3) มีราคาแพงหากไฟล์มีขนาดใหญ่ ตลกที่คุณพูดคำว่า "อันตราย"!
G-Man กล่าวว่า 'Reinstate Monica'

-1

คุณสามารถค้นหาไฟล์ในวิธีอื่นได้เสมอ ...

seq 10000000 >f
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
wc -l f; tail f

... พิมพ์ลำดับที่ดูแปลก ๆ :

10000000
10000001
10000002
10000003
10000004
10000005 f
9999996
9999997
9999998
9999999
10000000
new line!
new line!
new line!
new line!
new line!

แต่นั่นมันโง่นะ

ตัวอย่างที่มีประโยชน์มากขึ้นอาจมีลักษณะดังนี้:

 apnd() if    shift
        then  wc -l  >&2
              printf "$@"
        fi    <>"$1" >&0

คุณสามารถเรียกมันว่า:

 apnd /path/to/file          \
      "${printf_fmt_string}" \
       arbitrary list of strings

และคุณจะจบลงด้วยการนับจำนวนfileบรรทัดที่เขียนถึงstderrก่อนที่การดำเนินการผนวกจะเกิดขึ้น

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