`>>` dışında bir dosyanın sonuna satır eklemek için başka basit bir yol var mı?


21

Geçenlerde bir tree_holedosyaya kısa cümleler ekliyorum .

echo 'something' >> tree_holeBu işi yapmak için kullanıyordum .

Ama her zaman ne olursa yanlış girişin endişelendim >yerine >>sık sık bunu beri.

Bu yüzden bashrc'de kendime ait bir küresel bash işlevi yaptım:

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

Ama bir dosyanın sonuna satır eklemek için başka basit bir yol olup olmadığını merak ediyorum. Çünkü bunu başka durumlarda da kullanmam gerekebilir.

Var mı


9
Her giriş yaptığınızda egzersizi kullandığınızı unutmayacaksınız>? Bir zamanlar takma isimlerim vardı rm="rm -i"ve başka bir ortamda rm *onaylama sorularını bekleyerek yazdım . Tehlikeli alışkanlıklar öğreniyorsun!
Walter A

9
@WalterAer, "geçici çözümü" >> yerine >> yazmasına izin vermiyor, takma ad tanımsızsa hiçbir şey yapmadan "th some_sentence" ı çalıştırıyor.
Random832

1
@ Ranom832 onun etrafında çalışma için doğru. Uyarı noclobber benzeri bir "çözüm" içindir. Normal kabuğunda noclobber gibi bir şey kullandığında, geçici bir kök olduğu ve bir şey eklemek istediği zaman kullanabilir.
Walter A

7
@ Random832 & WalterA Normalde gördüğümde bu konuda hiçbir şey demiyorum, ancak arada bir arkadaşça bir notun yararlı olacağını düşündüm. Zen'in kullanıcı profili fazla ayrıntıya sahip değil, bu yüzden onun "geçici çözümünün" doğru form olduğunu gerçekten bilip bilmediğinizden emin değilim . Belki onların "geçici çözümü" veya OP'nin "geçici çözümü" demelisiniz . Belki de Zen'i şahsen tanıyorsunuz ve bu nedenle onun doğru olduğunu biliyorsunuz , bu durumda lütfen gürültüyü affedin. Çok fazla bir şey değil, sadece söylüyorum çünkü bu formu benim hakkımda konuşmak için kullanmış olsaydınız çok fazla takdir edemeyeceğimi biliyorum.
Celada

1
@Zen, >> yerine yanlış giriş yaptığınız için endişelendiğinizi yazdınız. Celada'nın planı çevrenizdeki riskleri ortadan kaldıracak ve sizin için iyi bir çözümdür. Komşunuza yardım ederken (noclobber'ı olmayan veya ksh kullanıyor) ve bir veya iki karakter> için dikkatinizi yitirmişseniz, yanlışlıkla dosyalarından birinin üzerine yazabilirsiniz. Noclobber uyarısını her zaman kendi ortamınızda aldığınızda, Tanrıya veya Celada'ya şükredin, kendinize söyleyin: Ohh, lütfen dikkatlice olun!, Başınızı sallayın ve iki saniye bekleyin.
Walter A

Yanıtlar:


47

Kabuğun noclobberseçeneğini ayarlayın :

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
Bu kesin cevaptır. Zorla yaparsanız, dosyanın üzerine hala yazabileceğinizi unutmayın >|. zshbu davranışı varsayılan olarak etkinleştirir.
orion

1
@orion Nasıl zsh içinde onu devre dışı bırakırsınız / devre dışı bırakırsınız? Açıkça devre dışı bırakıldığımı hatırlamıyorum, ancak üzerine yazmak zsh'mde iyi çalışıyor.
muru

2
Bu setopt noclobberve setopt clobber. Görünüşe göre tam olarak "varsayılan" değil, dağıtımınızla birlikte verilen yapılandırma dosyalarına bağlı.
orion

@muru set [+-]Cherhangi bir modern kabuk için çalışmalıdır
mikeserv 12:15

3
Basta @Zen set +o noclobber, veya set +C.
Ruslan

7

Eğer dosya ile zarar görür endişeli iseniz >operatöre sen ekleyecek şekilde dosya özelliğini değiştirebilecek yegâne:
In ext2 / ext3 / ext4 dosya sistemi: chattr +a file.txt
In XFS dosya sistemi:echo chattr +a | xfs_io file.txt

Ve eğer bir işlev istiyorsanız, kendim için bir işlev yaptım (çıktıları kaydetmek için servis dosyasında kullandım), amacınız için değiştirebilirsiniz:

# 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
Bu komut dosyasında birkaç sorun var. 1) $Küreselleşmeyi, sözcük bölünmesini ve ilgili boşluk sorunlarını önlemek için genellikle parametre genişletmelerinin (a ile başlayan şeyler) etrafına çift tırnak işareti koymalısınız . Çevrimiçi ShellCheck uygulaması bash betiğinde bu ve diğer çeşitli problemleri yakalayabilir. İlgili bir "$@"olduğunu çok daha güvenli $*.
PM 2Ring

3
2) Girişteki ters eğik çizgilerin aşağıdaki karakterden kaçmasını önlemek için, normal olarak readkomutu çağırmalısınız -r. 3) Kod değişkenleri için küçük harf kullanmak bash betiklerinde normaldir, çünkü ALL UPPER CASE sistem değişkenleri için kullanılır. Dolayısıyla, kendi değişkenleriniz için büyük harf kullanırsanız, kodunuzu okuyan kişilerin kafasını karıştırırsınız ve yanlışlıkla komut dosyasında daha sonra kullanmak istediğiniz bir sistem değişkenini yanlışlıkla engelleyebilirsiniz. Ve betiği kaynak yaparsanız , sonraki komutlar için değişkenleri engeller.
PM 2Ring

3
4) echosabit karakter dizileri yazdırmak için kullanışlıdır, ancak özellikle GNU sistemlerinde rastgele verilerle beklenmedik şeyler yapabilir. Bu var uzakta kullanılması daha güvenlidir printf. Daha fazla bilgi için unix.stackexchange.com/questions/65803/… 'e bakın , özellikle Stéphane Chazelas'ın cevabı.
PM 2Ring

3
@ PM 2Ring, Bugün sizden çok şey öğrendim, Çok teşekkürler .. Onları en kısa sürede düzelteceğim.
Sepahrad Salour

1
İyi işti, Sepahrad!
PM 2Ring

3

Kullanım teeekleme seçeneği ile:

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

5
İyi fikir, +1, ancak OP bir >karakteri unutmaktan endişe duyuyorsa, o zaman -aseçeneği unutmaktan endişe duyduklarını hayal ediyorum !
Celada

@Celada Sanırım (ama bir tekrarlanan tuş vuruşunda bir tuşa basılmasının bir yazım hatası seçeneğinin unutulmasından daha muhtemel olduğunu tahmin ediyorum).
muru

0

dosyaları üzerine yazmak için açabilen birçok program alternatif olarak bunları ekleme için açabilir, örneğin, gnu dd.

dd conv=notrunc oflag=append of=file

Bayt sayısını bastırmak için stdin veya if= add parametresindeki bir dosyayı okuyabilir 2>/dev/null.


3
Cevap olarak göndermeden önce kodunuzu test etmek iyi bir fikir ...
PM 2Ring

1
Tavsiye etmek ddkötü bir fikirdir. onlardan biri normal bir dosya ya da blok aygıtı olmadığında dd, çıktılarını güvenilir bir şekilde yazmaz
Gilles 'SO-'

@ gilles, bu bağlantıdaki bilgiyi yanlış veriyorsunuz, sayım belirtilmediğinde dd, cat'ın yaptığı gibi mevcut tüm verileri kopyalayacak.
Jasen,

-1

Kullanmak istiyorum sed(yedek kopya ile bile - uzantıya bakınız -i):

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

Neden şaşırmadım ki ... sen tam bir manyaksın, Costas. :) (Bu bir iltifat, BTW)
PM 2Ring

@ PM2Ring Evet, çok tehlikeliyim! : P
Costas

Elbette, çalışma şekli dosyanın bir kopyasını çıkarmak, sonuna kadar yeni metni ekleyin, sonra orijinal dosyayı silin ve kopyayı orijinal adına yeniden adlandırın. Bu (1), dizine yazma erişiminiz yoksa çalışmaz, (2) bağlantıları keser ve dosya büyükse (3) kaynak açısından pahalıdır. Komik olduğunu sen "tehlikeli" sözcüğü kadar getirdi!
G-Man 'Reinstate Monica' diyor

-1

Dosyayı her zaman başka yollarla arayabilirsin ...

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

... garip görünen sıralar basıyor:

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

Ama bu çok saçma.

Daha kullanışlı bir örnek şöyle görünebilir:

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

Gibi arayabilirsin:

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

Ekleme eylemi gerçekleşmeden hemen önce fileyazdığınız sayının satırlarını stderryazacaksınız.

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.