Gibt es eine andere einfache Möglichkeit, eine Zeile an das Dateiende anzuhängen, als ">>"?

21

Kürzlich habe ich kurze Sätze zu einer tree_holeDatei wiederholt .

Ich echo 'something' >> tree_holehabe diesen Job gemacht.

Aber ich war immer besorgt, was , wenn ich falsch Eingabe >statt >>, da ich dies oft getan hat.

Also habe ich eine eigene globale Bash-Funktion in der Bash-Funktion erstellt:

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

Aber ich frage mich, ob es eine andere einfache Möglichkeit gibt, Zeilen an das Ende einer Datei anzuhängen. Weil ich das bei anderen Gelegenheiten oft benutzen muss.

Gibt es irgendwelche?

Zen
quelle
9
Vergessen Sie nicht, dass Sie die Umgehungslösung bei jeder Eingabe von> verwenden? Einmal hatte ich einen Alias rm="rm -i"und habe in einer anderen Umgebung rm *auf die Bestätigungsfragen gewartet. Sie lernen gefährliche Gewohnheiten!
Walter A
9
@WalterA ähm, seine "Problemumgehung" lässt ihn nicht> statt >> eingeben, sondern führt nur "some_sentence" aus, was nichts bewirkt, wenn der Alias ​​undefiniert ist.
Random832
1
@Ranom832 richtig für seine th Abhilfe. Die Warnung ist für eine "Lösung" wie Noclobber. Wenn er so etwas wie Noclobber in seiner normalen Hülle verwendet, könnte er> verwenden, wenn er temporär root ist und etwas anhängen möchte.
Walter A
7
@ Random832 & WalterA Normalerweise sage ich nichts darüber, wenn ich es sehe, aber ich dachte mir, dass ein freundlicher Hinweis von Zeit zu Zeit nützlich sein könnte. Das Benutzerprofil von Zen hat nicht viele Details, daher bin ich mir nicht sicher, ob Sie wirklich wissen, dass seine "Problemumgehung" die richtige Form ist. Vielleicht sollten Sie ihre "Problemumgehung" oder die "Problemumgehung" des OP sagen . Vielleicht kennen Sie Zen persönlich und wissen daher, dass er richtig ist. In diesem Fall entschuldigen Sie bitte den Lärm. Keine große Sache, ich erwähne es nur, weil ich weiß, dass ich es nicht sehr geschätzt hätte, wenn Sie diese Form benutzt hätten, um über mich zu sprechen.
Celada,
1
@Zen, Sie haben geschrieben, Sie befürchten eine falsche Eingabe> anstelle von >>. Celadas Plan wird die Risiken in Ihrer Umgebung beseitigen und ist eine gute Lösung für Sie. Wenn Sie Ihrem Nachbarn helfen (der keinen Noclobber hat oder ksh verwendet) und Ihre Aufmerksamkeit für ein oder zwei Zeichen verloren haben, können Sie versehentlich eine seiner Dateien überschreiben. Also, Gott sei Dank oder Celada, sagt euch jedes Mal, wenn in eurer eigenen Umgebung die Noclobber-Warnung angezeigt wird: Ohh, sei vorsichtig, bitte !, schüttelt den Kopf und wartet zwei Sekunden.
Walter A

Antworten:

47

Legen Sie die noclobberOption der Shell fest :

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
quelle
3
Dies ist die endgültige Antwort. Beachten Sie, dass Sie die Datei immer noch überschreiben können, wenn Sie sie mit erzwingen >|. zshAktiviert dieses Verhalten standardmäßig.
Orion
1
@orion Wie kann man es in zsh aktivieren / deaktivieren? Ich kann mich nicht erinnern, es explizit deaktiviert zu haben, aber das Überschreiben funktioniert auf meinem zsh einwandfrei.
Muru
2
Es ist setopt noclobberund setopt clobber. Es sieht so aus, als ob es nicht genau "Standard" ist, es hängt von den Konfigurationsdateien ab, die mit Ihrer Distribution geliefert werden.
Orion
@muru sollte mit set [+-]Cjeder modernen Shell
funktionieren
3
@ Zen set +o noclobberin Bash oder set +C.
Ruslan
7

Wenn Sie befürchten, dass Ihre Datei vom >Bediener beschädigt wird, können Sie Ihr Dateiattribut so ändern, dass es nur angehängt wird:
Im ext2 / ext3 / ext4- Dateisystem: chattr +a file.txt
Im XFS- Dateisystem:echo chattr +a | xfs_io file.txt

Und wenn Sie eine Funktion möchten, habe ich sie bereits für mich selbst erstellt (ich habe sie in der Servicedatei zum Protokollieren von Ausgaben verwendet). Sie können sie für Ihren Zweck ändern:

# 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
quelle
2
Es gibt einige Probleme mit diesem Skript. 1) Sie sollten Parametererweiterungen (die mit a beginnen $) generell in doppelte Anführungszeichen setzen , um Globen, Worttrennung und damit verbundene Leerzeichenprobleme zu vermeiden. Die Online- ShellCheck- App kann dieses und verschiedene andere Probleme in Bash-Skripten erkennen. In einem ähnlichen Sinne "$@"ist viel sicherer als $*.
PM 2Ring
3
2) Normalerweise sollten Sie den readBefehl mit der -rOption aufrufen , um zu verhindern, dass Backslashes in der Eingabe das folgende Zeichen übergehen. 3) In Bash-Skripten ist es üblich, für Skriptvariablennamen Kleinbuchstaben zu verwenden, da ALL UPPER CASE für Systemvariablen verwendet wird. Wenn Sie also für Ihre eigenen Variablen Großbuchstaben verwenden, verwirren Sie Personen, die Ihren Code lesen, und Sie können versehentlich eine Systemvariable blockieren, die Sie später im Skript verwenden möchten. Wenn Sie das Skript als Quelle angeben, werden die Variablen für nachfolgende Befehle überlastet.
PM 2Ring
3
4) echoist praktisch zum Drucken von festen Zeichenfolgen, kann jedoch unerwartete Dinge mit beliebigen Daten tun, insbesondere auf GNU-Systemen. Es ist viel sicherer zu bedienen printf. Weitere Informationen, insbesondere die Antwort von Stéphane Chazelas, finden Sie unter unix.stackexchange.com/questions/65803/… .
PM 2Ring
3
@PM 2Ring, Heute habe ich viele Dinge von dir gelernt. Vielen Dank. Ich werde sie so schnell wie möglich reparieren.
Sepahrad Salour,
1
Gute Arbeit, Sepahrad!
PM 2Ring
3

Verwenden Sie teemit der Option zum Anhängen:

foo | tee -a some-file
# or
tee -a some-file <<EOF
blah blah
EOF
# or 
tee -a some-file <<<"blah blah"
muru
quelle
5
Gute Idee, +1, aber ich stelle mir vor, dass die OPs besorgt sind, >die -aOption zu vergessen, wenn sie sich Sorgen machen, einen Charakter zu vergessen !
Celada,
@ Celada Ich nehme das an (aber ich würde vermuten, dass ein Tippfehler, wenn ein Tastendruck in einer Reihe von wiederholten Tastenanschlägen fehlt, wahrscheinlicher ist, als eine Option zu vergessen).
Muru
0

Viele Programme, die Dateien zum Überschreiben öffnen können, können sie alternativ zum Anhängen öffnen, z. B. gnu dd.

dd conv=notrunc oflag=append of=file

Es kann stdin oder eine im if= Parameter add angegebene Datei lesen, um die Byteanzahl 2>/dev/nullzu unterdrücken.

Jasen
quelle
3
Es ist eine gute Idee, Ihren Code zu testen, bevor Sie ihn als Antwort veröffentlichen ...
PM 2Ring
1
Empfehlen ddist eine schlechte Idee. ddnicht zuverlässig seinen Eingang mit seinem Ausgang schreiben , nicht , wenn eine von ihnen nicht eine normale Datei oder Block - Gerät ist
Gilles ‚SO- Anschlag arg‘
@gilles, Sie stellen die Informationen unter diesem Link falsch dar. Wenn count nicht angegeben ist, kopiert dd alle verfügbaren Daten, genau wie cat.
Jasen
-1

Ich würde gerne eine verwenden sed(auch mit Sicherungskopie - siehe Erweiterung danach -i):

sed -i.bak '$ a\something' /Users/zen1/zen/pythonstudy/tree_hole
Costas
quelle
Warum wundert es mich nicht? Du bist ein verrückter Verrückter, Costas. :) (Das ist ein Kompliment, übrigens)
PM 2Ring
@ PM2Ring Ja, ich bin sehr gefährlich! : P
Costas
Natürlich funktioniert es, eine Kopie der Datei zu erstellen, den neuen Text am Ende hinzuzufügen, die Originaldatei zu löschen und die Kopie in den Originalnamen umzubenennen. Dies (1) funktioniert nicht, wenn Sie keinen Schreibzugriff auf das Verzeichnis haben, (2) Verknüpfungen unterbrechen und (3) bei großen Dateien ressourcenintensiv sind. Komisch, dass du das Wort "gefährlich" benutzt hast !
G-Man sagt, dass Monica
-1

Sie können die Datei jederzeit auf andere Weise durchsuchen ...

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

... diese seltsam aussehende Sequenz druckt:

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

Aber das ist irgendwie albern.

Ein nützlicheres Beispiel könnte so aussehen:

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

Sie können es so nennen:

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

Und Sie würden mit einer Anzahl von fileZeilen enden, die geschrieben wurden, stderrbevor die Aktion zum Anhängen stattfindet.

mikeserv
quelle