C'è un altro modo semplice per aggiungere una riga alla fine del file diverso da `>>`?


21

Recentemente sto facendo eco a brevi frasi in un tree_holefile.

Stavo usando echo 'something' >> tree_holeper fare questo lavoro.

Ma ero sempre preoccupato di cosa avrei fatto se avessi inserito male >invece di>> , dato che lo facevo spesso.

Così ho creato una mia funzione bash globale nella bashrc:

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

Ma mi chiedo se esiste un altro modo semplice per aggiungere linee alla fine di un file. Perché potrei aver bisogno di usarlo spesso in altre occasioni.

C'è qualche?


9
Non dimenticherai che stai usando la soluzione alternativa ogni volta che entri>? Una volta ho avuto un alias rm="rm -i"e in un altro ambiente ho scritto in rm *attesa delle domande di conferma. Stai imparando abitudini pericolose!
Walter A,

9
@WalterA er, la sua "soluzione alternativa" non gli consente di digitare> invece di >>, esegue solo "th some_sentence", che non fa nulla se l'alias non è definito.
Casuale 832,

1
@ Ranom832 corretto per la sua soluzione. L'avvertimento è per una "soluzione" come noclobber. Quando usa qualcosa come noclobber nel suo guscio normale, potrebbe usare> quando è root temporaneo e vuole aggiungere qualcosa.
Walter A,

7
@ Random832 & WalterA Di solito non dico nulla su questo quando lo vedo, ma ho pensato che forse un avviso amichevole di tanto in tanto potesse essere utile. Il profilo utente di Zen non ha molti dettagli, quindi non sono sicuro che tu sappia davvero che la sua "soluzione alternativa" è la forma corretta. Forse dovresti dire la loro "soluzione alternativa" o la "soluzione alternativa" del PO . Forse conoscete personalmente Zen e si sa dunque che la sua è corretto, in questo caso, si prega di perdonare il rumore. Non è un grosso problema, lo dico solo perché so che non l'avrei apprezzato molto se avessi usato quel modulo per parlare di me.
Celada,

1
@Zen, hai scritto che sei preoccupato di inserire male> invece di >>. Il piano di Celada eliminerà i rischi nel tuo ambiente ed è una buona soluzione per te. Quando aiuti il ​​tuo vicino (che non ha noclobber o sta usando ksh) e hai perso la tua attenzione per uno o due> personaggi, potresti sovrascrivere accidentalmente uno dei suoi file. Quindi ogni volta che ricevi l'avvertimento del noclobber nel tuo ambiente, grazie a Dio o Celada, dì a te stesso: Ohh, sii attento, per favore !, scuoti la testa e aspetta due secondi.
Walter A,

Risposte:


47

Imposta l' noclobberopzione della shell :

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
Questa è la risposta definitiva. Nota che puoi sempre sovrascrivere il file se lo imponi >|. zshabilita questo comportamento per impostazione predefinita.
Orione,

1
@orion Come si attiva / disattiva in zsh? Non ricordo di averlo disabilitato esplicitamente, ma la sovrascrittura funziona bene sul mio zsh.
Muru,

2
È setopt noclobbere setopt clobber. Sembra che non sia esattamente "predefinito", dipende dai file di configurazione forniti con la distribuzione.
Orione,

@muru dovrebbe funzionare con set [+-]Cqualsiasi shell moderna
mikeserv

3
@Zen set +o noclobberin bash, o set +C.
Ruslan,

7

Se sei preoccupato che il tuo file venga danneggiato >dall'operatore, puoi modificare l'attributo del file in modo da aggiungerlo solo:
Nel filesystem ext2 / ext3 / ext4 : chattr +a file.txt
Nel filesystem XFS :echo chattr +a | xfs_io file.txt

E se vuoi una funzione, ho già creato una funzione per me stesso (l'ho usata nel file di servizio per la registrazione degli output), puoi cambiarla per il tuo scopo:

# 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
Ci sono alcuni problemi con questo script. 1) Dovresti generalmente mettere le virgolette doppie intorno alle espansioni dei parametri (elementi che iniziano con a $) per evitare globbing, divisione delle parole e problemi relativi agli spazi bianchi. L' app ShellCheck online può rilevare questo e vari altri problemi negli script bash. In una nota correlata "$@"è molto più sicuro di $*.
PM 2Ring

3
2) Normalmente è necessario chiamare il readcomando con l' -ropzione per impedire a eventuali barre rovesciate nell'input di sfuggire al carattere seguente. 3) È usuale negli script bash usare lettere minuscole per i nomi delle variabili di script poiché ALL UPPER CASE viene usato per le variabili di sistema. Quindi, se usi le maiuscole per le tue variabili confonderai le persone che leggono il tuo codice e potresti accidentalmente intasare una variabile di sistema che vuoi usare in seguito nello script. E se si genera lo script, bloccherà le variabili per i comandi successivi.
PM 2Ring

3
4) echoè utile per stampare stringhe fisse, ma può fare cose inaspettate con dati arbitrari, specialmente su sistemi GNU. È molto più sicuro da usare printf. Vedi unix.stackexchange.com/questions/65803/… per maggiori informazioni, in particolare la risposta di Stéphane Chazelas.
PM 2Ring

3
@PM 2Ring, oggi ho imparato molte cose da te, grazie mille .. Le riparerò il prima possibile.
Sepahrad Salour,

1
Bel lavoro, Sepahrad!
PM 2Ring

3

Utilizzare teecon l'opzione Aggiungi:

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

5
Buona idea, +1, ma immagino che se l'OP è preoccupato di dimenticare un >personaggio, potrebbe essere preoccupato di dimenticare l' -aopzione!
Celada,

@Celada Suppongo di sì (ma immagino che un errore di battitura per la mancanza di una sequenza di tasti in una serie di sequenze di tasti ripetute abbia più probabilità di accadere che dimenticare un'opzione).
Muru,

0

molti programmi che possono aprire file per la sovrascrittura possono alternativamente aprirli per aggiungere, ad esempio gnu dd.

dd conv=notrunc oflag=append of=file

può leggere stdin o un file chiamato nel if= parametro add 2>/dev/nullper sopprimere il conteggio dei byte.


3
È una buona idea ™ testare il codice prima di pubblicarlo come risposta ...
PM 2Ring

1
Raccomandare ddè una cattiva idea. ddnon scrive in modo affidabile il suo input nel suo output , non quando uno di loro non è un normale file o blocca il dispositivo
Gilles "SO - smetti di essere malvagio"

@gilles, stai travisando le informazioni a quel link, quando count non è specificato dd copierà tutti i dati disponibili, proprio come fa cat.
Jasen,

-1

Vorrei usare un sed(anche con backup-copy - vedi estensione dopo -i):

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

Perché non sono sorpreso ... sei un maniaco sed, Costas. :) (È un complimento, a proposito)
PM 2Ring

@ PM2Ring Sì, sono molto pericoloso! : P
Costas,

Ovviamente il modo in cui funziona è fare una copia del file, aggiungere il nuovo testo alla fine, quindi eliminare il file originale e rinominare la copia con il nome originale. Questo (1) non funziona se non si ha accesso in scrittura alla directory, (2) interrompe i collegamenti e (3) è costoso se il file è di grandi dimensioni. Divertente che tu abbia menzionato la parola "pericoloso"!
G-Man dice "Ripristina Monica" l'

-1

Puoi sempre cercare nel file in altri modi ...

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

... quella sequenza dall'aspetto strano stampa:

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

Ma è un po 'sciocco.

Un esempio più utile potrebbe apparire come:

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

Puoi chiamarlo come:

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

E finiresti con un conteggio delle filerighe scritte stderrappena prima che abbia luogo l'azione append.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.