Bash'deki bir dosyanın başlangıcına nasıl metin eklerim?


285

Merhaba, bir dosyaya metin hazırlamak istiyorum. Örneğin, bir todo.txt dosyasının başına görev eklemek istiyorum. Farkındayım echo 'task goes here' >> todo.txtama bu dosyayı sonuna kadar ekler (istediğim şeyi değil).


2
Büyük dosyalar için bunu yapmanın etkili bir yolu yoksa: unix.stackexchange.com/questions/87772/…
Ciro Santilli

@ bu yönteme bir göz atar mısın superuser.com/a/1352628/11116
Evan Carroll

Yanıtlar:


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

veya

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

veya

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

4
İlki harika çalışıyor! mantığı açıklar mısın? im sözdizimini nasıl yorumlayacağımı bilmiyorum.
user479534

44
@ user8347: Birinci dosya olarak ve ikinci olarak (standart girdi) kullanan |mesajı ( echo '...') yönlendirin . conCATenate birden fazla dosya. Output ( ) adlı bir dosyaya gönderin . Hata yoksa ( ), o zaman yeniden adlandırın ( ), dosyayı orijinal dosyaya ( ) geri döndürün . cat-todo.txtcat>temp&&catmvtemptodo.txt
Dennis Williamson,

1
@itaifrenkel: Ne yaptığınızı görmek zorunda kaldım, ancak catdeğişmez bir ters eğik çizgi alırsa, onu yeni bir satıra dönüştürmez. Bunu başka bir şey yapmış olmalı. Bunun yerine, gerçekte ters eğik çizgi gönderip göndermediğinizi veya yeni bir satır olup olmadığını görmek için catboruları deneyin hexdump -C. Ayrıca cat -esatır sonlarını da göstermeyi deneyebilirsiniz .
Dennis Williamson

1
2 ve 3'ü kullanmak (3, bana daha basit görünüyor) bir kerede birçok dosyaya metin hazırlamanızı sağlar .
Felix

4
@Kira: Bu 1, bir sonraki komutu yalnızca dosyanın satırında yapar ve komut eklenir i. "Adresler" bölümünün altındaki ve "Sıfır veya Tek adres komutları" bölümündeki man sayfasına bakın.
Dennis Williamson,

73

Bence daha basit bir seçenek:

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

Bu çalışır çünkü içindeki komutun üzerine $(...)çalıştırılır.todo.txt> todo.txt

Diğer cevaplar iyi çalışırken, hatırlamak çok daha kolay çünkü her gün yankı ve kedi kullanıyorum.

EDIT: Eğer ters eğik çizgi varsa bu çözüm çok kötü bir fikir todo.txt, çünkü -ebayrak sayesinde yankı onları yorumlayacak. Yeni satırları önsöz dizgisine eklemenin çok daha kolay bir yolu ...

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

... sadece yeni satırları kullanmak için. Tabii ki, artık bir astar değil, ama gerçekçi olarak, daha önce de bir astar değildi. Bunu bir komut dosyası içinde yapıyorsanız ve girintileme konusunda endişeleniyorsanız (örneğin, bunu bir işlevin içinde yürütüyorsunuz), bunun da dahil olmak ancak bunlarla sınırlı olmamak üzere, güzel bir şekilde sığmaya devam etmesi için birkaç geçici çözüm vardır:

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

Ayrıca, yeni bir satırın sonuna eklenip eklenmediğini önemsiyorsanız todo.txt, bunları kullanmayın. Şey, ikinci-sonuncusu hariç. Bu, sonu karıştırmaz.


1
Hiç $ (...) idam edilmiyorum.
SCL

2
Tek yerine çift tırnak işareti ile daha iyi (ya da hiç) işe yarayabilir…
ℝaphink

5
Olmaz -eda todo.txt içine kaçış dizileri dönüştürmek?
mk12

2
Geçici Çözümler verim -> cat: <hedef dosya adı>: giriş dosyası çıkış dosyasıdır ...
Ocak'ta 15:15

printf, platformlar arasında çok daha tutarlı olacaktır ve genellikle eko-e'den daha sorunsuz çalışmalıdır
Peter Berg

28

moreutilsAdlı güzel bir araca sahip sponge:

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

STDIN'i "ıslatır" ve ardından dosyaya yazılır, bu da geçici dosyalar hakkında endişelenmenize gerek kalmadan dosyaları taşımak zorunda kalmayacağınız anlamına gelir.

Sen alabilirsiniz moreutilsboyunca, pek çok Linux dağıtımlarının ile apt-get install moreutilskullanarak veya OS X'de Homebrew ile brew install moreutils.


(echo 'ble'; cat todo.txt):-) için giderdim
Ciro Santilli 9

11

Vim'i Ex modunda kullanabilirsiniz:

ex -s -c '1i|task goes here' -c x todo.txt
  1. 1 ilk satırı seç

  2. i eklemek

  3. x kaydet ve kapat


5

Yeni, geçici bir dosya oluşturabilirsiniz.

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

Ayrıca sedveya kullanabilirsiniz awk. Ama temelde aynı şey olur.


1
Diyelim ki disk alanınız bitti, böylece new_todo.txtsadece kısmen yazılabilir. Çözümünüz orijinal dosyayı kaybediyor.
NPE

Kim disk alanı azalıyor? ;-) Sadece basit bir örnek.
Keith,

2
@Keith Özellikle büyük bir sanal sürücüye ihtiyaç duymayı beklemeyen bir VM üzerinde çalışan biri. Ya da büyük bir dosyayı taşıyan biri. Her durumda, buna karşı gerçek argüman dizin izinleri; Belirtilen dizinde yeni dosyalar oluşturma izniniz yoksa, betiğinizde başarılı bir şekilde yürütülecek tek komut rmorijinal dosyaya aittir.
Parthian Shot

3

Metin dosyası belleğe sığacak kadar küçükse, onunla değiştirmek için geçici bir dosya oluşturmanız gerekmez. Hepsini hafızaya yükleyebilir ve dosyaya geri yazabilirsiniz.

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

Dosyanın tamamına yazı yazmadan satır başına satır eklemek mümkün değildir.


Sadece açık soruyu sormak için: Kabuk değişkenlerinin karakter sınırı nerede?
nixda

Bildiğim kadarıyla, sadece mevcut bellek miktarı ile sınırlıdır. 100 MB'ın üzerindeki değişkenleri belleğe doldurdum. text=$(cat file). Kabuk değişkenleri değil ikili temiz olduğundan olsa tek kullanım metne dikkat mywiki.wooledge.org/BashFAQ/058
Rucent88

2

Dosyanın başına içerik ekleyemezsiniz. Yapabileceğiniz tek şey, mevcut içeriğin yerini almak veya dosyanın sonundan sonra bayt eklemek.

Sorunuzla ilgili herhangi bir çözüm, sonunda özgün dosyanın üzerine yazacak (bellekte veya diskte) geçici bir dosya (veya arabellek) oluşturulmasını gerektirir.

Yeni dosya oluşturulurken orijinal dosyayı koruyarak veri kaybetmemeye dikkat edin, dosya sistemi işlem sırasında tamamen doluysa. Örneğin:

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

Katılımcıların motivasyonlarını açıklamaları rica olunur. Kabul edilenler de dahil olmak üzere kalan cevapların hiçbiri cevabımdaki hiçbir şeyle çelişmiyor.
jlliagre

Bunu, ayrılmayacağını varsaydığım parantezlere benzeyen <...> ayrıştırmak zor. <Ve # (boşluk olabilir mi?) Arasındaki boşluk
dumbledad

Bu benim için çalışmıyor. echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'çalışır ancak cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'"echo: Böyle bir dosya veya dizin yok" hatası veriyor
dumbledad

@ dumbledad Cevabımı fazla gözden geçiriyorsun. Ayrıştırmanız gereken hiçbir şey yok. Arasında bir boşluk <ve (sözdizimi kırar. Deneyincat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
jlliagre


0

GitBash + Windows 10 + multline :

Çok satırlı dizeleri kullanmanızı sağlayan bir sürüm .

##############################################
## 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]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.