Apakah ada cara sederhana lain untuk menambahkan baris ke ujung file selain `>>`?

21

Baru-baru ini saya menggemakan kalimat pendek ke tree_holefile.

Saya menggunakan echo 'something' >> tree_holeuntuk melakukan pekerjaan ini.

Tetapi saya selalu khawatir bagaimana jika saya salah memasukkan >bukan >>, karena saya sering melakukan ini.

Jadi saya membuat fungsi bash global saya sendiri di bashrc:

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

Tapi saya bertanya-tanya apakah ada cara sederhana lain untuk menambahkan baris ke akhir file. Karena saya mungkin perlu sering menggunakannya dalam kesempatan lain.

Apakah ada?

Zen
sumber
9
Apakah Anda tidak lupa Anda menggunakan work-around setiap kali Anda masuk>? Pernah saya memiliki alias rm="rm -i"dan di lingkungan lain menulis rm *menunggu pertanyaan konfirmasi. Anda belajar kebiasaan berbahaya!
Walter A
9
@WalterA er, "solusi" tidak membiarkannya mengetik> bukan >>, ia hanya menjalankan "th some_sentence", yang tidak melakukan apa-apa jika alias tidak ditentukan.
Acak832
1
@ Ranom832 benar untuk pekerjaannya yang ke-5. Peringatan itu untuk "solusi" seperti noclobber. Ketika dia menggunakan sesuatu seperti noclobber di shell normalnya, dia mungkin menggunakan> ketika dia root sementara dan ingin menambahkan sesuatu.
Walter A
7
@ Random832 & WalterA Saya biasanya tidak mengatakan apa-apa tentang ini ketika saya melihatnya, tetapi saya pikir mungkin pemberitahuan ramah sesekali bisa berguna. Profil pengguna Zen tidak memiliki banyak detail, jadi saya tidak yakin apakah Anda benar-benar tahu bahwa "solusi" nya adalah bentuk yang benar. Mungkin Anda harus mengatakan "solusi" atau "solusi" dari OP . Mungkin Anda tahu Zen pribadi dan karena itu Anda tahu bahwa itu benar, dalam hal ini, maafkan kebisingan. Bukan masalah besar, saya hanya menyebutkannya karena saya tahu saya tidak akan sangat menghargainya jika Anda menggunakan formulir itu untuk membicarakan saya.
Celada
1
@ Zen, Anda menulis Anda khawatir salah input> bukan >>. Rencana Celada akan menghilangkan risiko di lingkungan Anda, dan merupakan solusi yang baik untuk Anda. Ketika Anda membantu tetangga Anda (yang tidak memiliki noclobber atau menggunakan ksh) dan Anda kehilangan perhatian untuk satu atau dua karakter, Anda mungkin secara tidak sengaja menimpa salah satu file-nya. Jadi, setiap kali Anda mendapat peringatan noclobber di lingkungan Anda sendiri, terima kasih Tuhan atau Celada, katakan pada diri sendiri: Ohh, harap hati-hati !, gelengkan kepala Anda dan tunggu dua detik.
Walter A

Jawaban:

47

Atur opsi shell 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$ 
Celada
sumber
3
Ini adalah jawaban yang pasti. Perhatikan bahwa Anda masih bisa menimpa file jika Anda memaksanya >|. zshmengaktifkan perilaku ini secara default.
orion
1
@ orion Bagaimana Anda menonaktifkan / menonaktifkannya di zsh? Saya tidak ingat secara eksplisit menonaktifkannya, tetapi menimpa berfungsi dengan baik pada zsh saya.
muru
2
Itu setopt noclobberdan setopt clobber. Tampaknya itu bukan "default", itu tergantung pada file konfigurasi yang dikirimkan bersama distro Anda.
orion
@uru harus bekerja dengan set [+-]Cshell modern
mikeserv
3
@ Zen set +o noclobberdalam bash, atau set +C.
Ruslan
7

Jika Anda khawatir file Anda akan rusak oleh > operator, Anda dapat mengubah atribut file Anda menjadi hanya menambahkan:
Dalam sistem file ext2 / ext3 / ext4 : chattr +a file.txt
Dalam sistem file XFS :echo chattr +a | xfs_io file.txt

Dan jika Anda menginginkan suatu fungsi, saya telah membuat suatu fungsi untuk diri saya sendiri (saya menggunakannya dalam file layanan untuk mencatat keluaran), Anda dapat mengubahnya untuk tujuan Anda:

# 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
}
Sepahrad Salour
sumber
2
Ada beberapa masalah dengan skrip ini. 1) Anda biasanya harus menempatkan tanda kutip ganda di sekitar ekspansi parameter (hal-hal yang dimulai dengan a $) untuk mencegah globbing, pemecahan kata dan masalah spasi spasi terkait Aplikasi ShellCheck online dapat menangkap ini dan berbagai masalah lainnya di skrip bash. Pada catatan terkait "$@"adalah jauh lebih aman daripada $*.
PM 2Ring
3
2) Anda biasanya harus memanggil readperintah dengan -ropsi untuk mencegah backslash dalam input lolos dari karakter berikut. 3) Biasanya dalam skrip bash untuk menggunakan huruf kecil untuk nama-nama variabel skrip karena SEMUA KASUS UPPER digunakan untuk variabel sistem. Jadi, jika Anda menggunakan huruf besar untuk variabel Anda sendiri, Anda akan membingungkan orang yang membaca kode Anda, dan Anda mungkin secara tidak sengaja memecahkan variabel sistem yang ingin Anda gunakan nanti dalam skrip. Dan jika Anda sumber skrip, itu akan menghancurkan variabel untuk perintah selanjutnya.
PM 2Ring
3
4) echoberguna untuk mencetak string tetap, tetapi dapat melakukan hal-hal yang tidak terduga dengan data arbitrer, terutama pada sistem GNU. Ini jauh lebih aman untuk digunakan printf. Lihat unix.stackexchange.com/questions/65803/… untuk info lebih lanjut, terutama jawaban Stéphane Chazelas.
PM 2Ring
3
@PM 2Ring, Hari ini saya belajar banyak hal dari Anda, terima kasih banyak .. Saya akan memperbaikinya sesegera mungkin.
Sepahrad Salour
1
Kerja bagus, Sepahrad!
PM 2Ring
3

Gunakan teedengan opsi append:

foo | tee -a some-file
# or
tee -a some-file <<EOF
blah blah
EOF
# or 
tee -a some-file <<<"blah blah"
muru
sumber
5
Ide bagus, +1, tapi saya membayangkan bahwa jika OP khawatir akan melupakan >karakter, mereka mungkin khawatir akan melupakan -aopsi!
Celada
@Celada saya kira begitu (tapi saya kira kesalahan ketik dari kehilangan satu keystroke dalam satu set penekanan tombol berulang kali lebih mungkin terjadi daripada melupakan opsi).
muru
0

banyak program yang dapat membuka file untuk ditimpa dapat juga membukanya untuk ditambahkan, misalnya gnu dd.

dd conv=notrunc oflag=append of=file

itu bisa membaca stdin atau file bernama dalam if= parameter add 2>/dev/nulluntuk menekan jumlah byte.

Jasen
sumber
3
Merupakan Ide yang Baik ™ untuk menguji kode Anda sebelum mempostingnya sebagai jawaban ...
PM 2Ring
1
Merekomendasikan ddadalah ide yang buruk. ddtidak andal menulis inputnya ke outputnya , tidak ketika salah satu dari mereka bukan file atau blok perangkat biasa
Gilles 'SO-stop being evil'
@ gilles, Anda salah mengartikan informasi di tautan itu, ketika hitungan tidak ditentukan dd akan menyalin semua data yang tersedia, sama seperti yang dilakukan kucing.
Jasen
-1

Saya ingin menggunakan sed(bahkan dengan salinan cadangan - lihat ekstensi setelah -i):

sed -i.bak '$ a\something' /Users/zen1/zen/pythonstudy/tree_hole
Costas
sumber
Mengapa saya tidak terkejut ... Anda adalah seorang maniak sed, Costas. :) (Itu pujian, BTW)
PM 2Ring
@ PM2Ring Ya, saya sangat berbahaya! : P
Costas
Tentu saja cara kerjanya adalah membuat salinan file, menambahkan teks baru ke bagian akhir, lalu menghapus file asli dan mengganti nama salinan menjadi nama aslinya. Ini (1) tidak berfungsi jika Anda tidak memiliki akses tulis ke direktori, (2) memecah tautan, dan (3) mahal sumber daya jika file tersebut besar. Lucu bahwa Anda membawa kata "berbahaya"!
G-Man Mengatakan 'Reinstate Monica'
-1

Anda selalu dapat mencari melalui file dengan cara lain ...

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

... urutan yang tampak aneh itu dicetak:

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

Tapi itu agak konyol.

Contoh yang lebih bermanfaat bisa terlihat seperti:

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

Anda bisa menyebutnya seperti:

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

Dan Anda akan berakhir dengan jumlah filebaris yang ditulis stderrsebelum tindakan menambahkan terjadi.

mikeserv
sumber