Bagaimana cara menambahkan teks ke awal file di Bash?
285
Hai, saya ingin menambahkan teks ke file. Misalnya saya ingin menambahkan tugas ke awal file todo.txt. Saya sadar echo 'task goes here' >> todo.txttetapi itu menambahkan baris ke akhir file (bukan yang saya inginkan).
yang pertama berhasil! maukah Anda menjelaskan logika? im tidak terlalu yakin bagaimana menafsirkan sintaks.
user479534
44
@ user8347: Pipa ( |) pesan ( echo '...') catyang menggunakan -(input standar) sebagai file pertama dan todo.txtsebagai yang kedua. catbuat beberapa file. Kirim output ( >) ke file bernama temp. Jika tidak ada kesalahan ( &&) sejak catsaat itu ganti nama ( mv) tempfile kembali ke file asli ( todo.txt).
Dennis Williamson
1
@itaifrenkel: Saya harus melihat apa yang Anda lakukan, tetapi jika catmenerima backslash n literal, itu tidak akan mengubahnya menjadi baris baru. Sesuatu yang lain pasti telah melakukan itu. Alih-alih cat, coba pilih hexdump -Capakah Anda benar-benar mengirim backslash dan n atau apakah itu baris baru. Anda juga dapat mencoba cat -emenampilkan akhiran garis.
Dennis Williamson
1
Menggunakan 2 dan 3 (3 tampaknya lebih mudah bagi saya) memungkinkan Anda untuk menambahkan teks ke banyak file sekaligus.
Felix
4
@ Kirira: Cara 1melakukan perintah berikutnya hanya pada baris satu file dan iperintahnya adalah menyisipkan. Lihat di halaman manual di bawah bagian "Alamat" dan di bagian "Perintah nol atau satu alamat".
Ini berfungsi karena perintah di dalam $(...)dieksekusi sebelum todo.txtditimpa dengan> todo.txt
Sementara jawaban lain berfungsi dengan baik, saya menemukan ini jauh lebih mudah diingat karena saya menggunakan gema dan kucing setiap hari.
EDIT: Solusi ini adalah ide yang sangat buruk jika ada backslash todo.txt, karena berkat -eflag echo akan menafsirkannya. Cara lain yang jauh lebih mudah untuk memasukkan baris baru ke dalam kata pengantar adalah ...
echo "task goes here
$(cat todo.txt)"> todo.txt
... cukup menggunakan baris baru. Tentu, itu bukan satu-liner lagi, tetapi secara realistis itu bukan satu-liner sebelumnya, juga. Jika Anda melakukan ini di dalam skrip, dan khawatir tentang indentasi (misalnya Anda menjalankan ini di dalam suatu fungsi) ada beberapa solusi untuk membuat ini tetap pas, termasuk tetapi tidak terbatas pada:
Juga, jika Anda peduli apakah baris baru akan ditambahkan ke akhir todo.txt, jangan gunakan ini. Ya, kecuali yang kedua ke terakhir. Itu tidak mengacaukan akhirnya.
Ini akan "menyerap" STDIN dan kemudian menulis ke file, yang berarti Anda tidak perlu khawatir tentang file sementara dan memindahkannya.
Anda dapat moreutilsmenggunakan banyak distro Linux, melalui apt-get install moreutils, atau pada OS X menggunakan Homebrew , dengan brew install moreutils.
Katakanlah Anda kehabisan ruang disk sehingga new_todo.txthanya ditulis sebagian. Solusi Anda tampaknya kehilangan file asli.
NPE
Siapa yang kehabisan ruang disk? ;-) Ini hanya contoh sederhana.
Keith
2
@Keith Seseorang yang bekerja pada VM yang tidak berharap membutuhkan drive virtual yang sangat besar. Atau seseorang memindahkan file besar. Dalam kasus apa pun, argumen sebenarnya yang menentang hal ini adalah izin direktori; jika Anda tidak memiliki izin untuk membuat file baru di direktori yang diberikan, satu-satunya perintah yang akan berhasil dijalankan dalam skrip Anda adalah rmdari file asli.
Parthian Shot
3
Jika file teks cukup kecil untuk muat dalam memori, Anda tidak perlu membuat file sementara untuk menggantinya. Anda dapat memuat semuanya ke dalam memori dan menuliskannya kembali ke file.
Hanya untuk mengajukan pertanyaan yang jelas: Di mana batas karakter variabel shell?
nixda
Sejauh yang saya ketahui, itu hanya dibatasi oleh jumlah memori yang tersedia. Saya telah mengisi variabel lebih dari 100MB ke dalam memori. text=$(cat file). Berhati-hatilah untuk hanya menggunakan teks, karena variabel shell bukan biner bersih mywiki.wooledge.org/BashFAQ/058
Rucent88
2
Anda tidak dapat menyisipkan konten di awal file. Satu-satunya hal yang dapat Anda lakukan adalah mengganti konten yang ada atau menambahkan byte setelah akhir file saat ini.
Solusi apa pun untuk pertanyaan Anda kemudian membutuhkan file sementara (atau buffer) yang akan dibuat (pada memori atau pada disk) yang pada akhirnya akan menimpa file asli.
Waspadalah jangan sampai kehilangan data dengan menyimpan file asli saat membuat yang baru, jika sistem file terjadi penuh selama proses. misalnya:
Para downvoters dipersilakan untuk menjelaskan motivasi mereka. Tidak ada jawaban yang tersisa, termasuk yang diterima, yang bertentangan dengan jawaban saya.
jlliagre
Ini sulit untuk diurai karena <...> terlihat seperti tanda kurung, yang saya asumsikan tidak. Ruang antara <dan (mungkin bisa membantu?
dumbledad
Ini tidak bekerja untuk saya. echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'berfungsi tetapi cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'memberikan kesalahan "gema: Tidak ada file atau direktori"
dumbledad
@dumbledad Anda terlalu memikirkan balasan saya. Tidak ada yang bisa Anda uraikan. Ruang antara <dan (akan memecah sintaks. Cobacat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
jlliagre
1
Anda bisa menggunakan tee:
echo 'task goes here'| cat - todo.txt | tee todo.txt
Jawaban:
atau
atau
sumber
|
) pesan (echo '...'
)cat
yang menggunakan-
(input standar) sebagai file pertama dantodo.txt
sebagai yang kedua.cat
buat beberapa file. Kirim output (>
) ke file bernamatemp
. Jika tidak ada kesalahan (&&
) sejakcat
saat itu ganti nama (mv
)temp
file kembali ke file asli (todo.txt
).cat
menerima backslash n literal, itu tidak akan mengubahnya menjadi baris baru. Sesuatu yang lain pasti telah melakukan itu. Alih-alihcat
, coba pilihhexdump -C
apakah Anda benar-benar mengirim backslash dan n atau apakah itu baris baru. Anda juga dapat mencobacat -e
menampilkan akhiran garis.1
melakukan perintah berikutnya hanya pada baris satu file dani
perintahnya adalah menyisipkan. Lihat di halaman manual di bawah bagian "Alamat" dan di bagian "Perintah nol atau satu alamat".Pilihan yang lebih sederhana menurut saya adalah:
Ini berfungsi karena perintah di dalam
$(...)
dieksekusi sebelumtodo.txt
ditimpa dengan> todo.txt
Sementara jawaban lain berfungsi dengan baik, saya menemukan ini jauh lebih mudah diingat karena saya menggunakan gema dan kucing setiap hari.
EDIT: Solusi ini adalah ide yang sangat buruk jika ada backslash
todo.txt
, karena berkat-e
flag echo akan menafsirkannya. Cara lain yang jauh lebih mudah untuk memasukkan baris baru ke dalam kata pengantar adalah ...... cukup menggunakan baris baru. Tentu, itu bukan satu-liner lagi, tetapi secara realistis itu bukan satu-liner sebelumnya, juga. Jika Anda melakukan ini di dalam skrip, dan khawatir tentang indentasi (misalnya Anda menjalankan ini di dalam suatu fungsi) ada beberapa solusi untuk membuat ini tetap pas, termasuk tetapi tidak terbatas pada:
Juga, jika Anda peduli apakah baris baru akan ditambahkan ke akhir
todo.txt
, jangan gunakan ini. Ya, kecuali yang kedua ke terakhir. Itu tidak mengacaukan akhirnya.sumber
-e
juga mengonversi urutan pelarian di dalam todo.txt?The
moreutils
memiliki alat yang bagus disebutsponge
:Ini akan "menyerap" STDIN dan kemudian menulis ke file, yang berarti Anda tidak perlu khawatir tentang file sementara dan memindahkannya.
Anda dapat
moreutils
menggunakan banyak distro Linux, melaluiapt-get install moreutils
, atau pada OS X menggunakan Homebrew , denganbrew install moreutils
.sumber
(echo 'ble'; cat todo.txt)
:-)Anda dapat menggunakan Vim dalam mode Ex:
1
pilih baris pertamai
memasukkanx
Simpan dan tutupsumber
Anda dapat membuat file sementara yang baru.
Anda mungkin juga menggunakan
sed
atauawk
. Tetapi pada dasarnya hal yang sama terjadi.sumber
new_todo.txt
hanya ditulis sebagian. Solusi Anda tampaknya kehilangan file asli.rm
dari file asli.Jika file teks cukup kecil untuk muat dalam memori, Anda tidak perlu membuat file sementara untuk menggantinya. Anda dapat memuat semuanya ke dalam memori dan menuliskannya kembali ke file.
Tidak mungkin menambahkan baris ke awal file tanpa harus menulis seluruh file.
sumber
text=$(cat file)
. Berhati-hatilah untuk hanya menggunakan teks, karena variabel shell bukan biner bersih mywiki.wooledge.org/BashFAQ/058Anda tidak dapat menyisipkan konten di awal file. Satu-satunya hal yang dapat Anda lakukan adalah mengganti konten yang ada atau menambahkan byte setelah akhir file saat ini.
Solusi apa pun untuk pertanyaan Anda kemudian membutuhkan file sementara (atau buffer) yang akan dibuat (pada memori atau pada disk) yang pada akhirnya akan menimpa file asli.
Waspadalah jangan sampai kehilangan data dengan menyimpan file asli saat membuat yang baru, jika sistem file terjadi penuh selama proses. misalnya:
sumber
echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'
berfungsi tetapicat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'
memberikan kesalahan "gema: Tidak ada file atau direktori"<
dan(
akan memecah sintaks. Cobacat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
Anda bisa menggunakan
tee
:sumber
GitBash + Windows10 + Multline :
Ini adalah versi yang memungkinkan Anda menggunakan string multi-line .
sumber