Domanda

Questo è probabilmente una soluzione complessa.

Sto cercando un semplice operatore ">>", ma per anteporre.

Ho paura che non esiste.Dovrò fare qualcosa di simile

 mv myfile tmp
 cat myheader tmp > myfile

Nulla di più intelligente?

È stato utile?

Soluzione

Il hack di seguito un breve off-the-bracciale risposta che ha lavorato e ha ricevuto un sacco di upvotes.Quindi, la questione è diventato più popolare e più il tempo passava più indignato la gente ha iniziato a riferire che è sorta lavorato, ma strane cose potrebbero accadere, o che semplicemente non funzionano affatto, così è stato furiosamente downvoted per un periodo di tempo.Tale divertimento.

La soluzione sfrutta l'esatta attuazione di descrittori di file sul vostro sistema e, perché attuazione varia in modo significativo tra nixes, è successo è interamente dipendente dal sistema, in definitiva non portatile, e non dovrebbe essere invocata per qualsiasi cosa anche solo vagamente di importante.

Ora, con tutto che la risposta è stata:


La creazione di un altro descrittore di file per il fileexec 3<> yourfile) là scrittura (>&3 sembra superare la lettura/scrittura su file stesso dilemma.Per me funziona su 600K file con awk.Tuttavia cercare di fare lo stesso trucco con 'cat' non riesce.

Passando il prependage come variabile awk (-v TEXT="$text") supera le citazioni letterali, problema che impedisce di fare questo trucco con "sed".

#!/bin/bash
text="Hello world
What's up?"

exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3

Altri suggerimenti

Questo utilizza ancora un file temp, ma almeno è su una riga:

echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile

Credito: BASH:Aggiungere Un Testo / Linee Di un File

echo '0a
your text here
.
w' | ed some_file

ed è l'Editor Standard! http://www.gnu.org/fun/jokes/ed.msg.html

Giovanni Mee:il metodo di lavoro non è garantita, e probabilmente non se si antepone più di 4096 byte di roba (almeno questo è quello che succede con gnu awk, ma suppongo che altre implementazioni simili vincoli).Non solo fallire in quel caso, ma entra in un ciclo infinito in cui si potrà leggere la sua uscita, rendendo in tal modo il file di crescere fino a quando tutto lo spazio è riempito.

Provare per credere:

exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3

(avviso:uccidere dopo un po ' o si riempirà il filesystem)

Inoltre, è molto pericoloso per modificare i file che modo, ed è molto cattivi consigli, come se qualcosa accade mentre il file viene modificato (crash, disco pieno) si è quasi garantito per essere lasciato con il file in uno stato incoerente.

Non è possibile senza file temp, ma qui va un oneliner

{ echo foo; cat oldfile; } > newfile && mv newfile oldfile

È possibile utilizzare altri strumenti come ed o perl per farlo senza i file temp.

Può essere interessante notare che spesso è un buona idea sicuro di generare il file temporaneo utilizzando un programma di utilità come mktemp, almeno se lo script potrà mai essere eseguito con privilegi di root.Si potrebbe, per esempio, effettuare le seguenti operazioni (di nuovo in bash):

(tmpfile=`mktemp` && { echo "prepended text" | cat - yourfile > $tmpfile && mv $tmpfile yourfile; } )

Se avete bisogno di questo sul computer di controllo, installare il pacchetto "moreutils" e "spugna".Allora si può fare:

cat header myfile | sponge myfile

Utilizzando un bash heredoc è possibile evitare la necessità di un file tmp:

cat <<-EOF > myfile
  $(echo this is prepended)
  $(cat myfile)
EOF

Questo funziona perché $(cat mio_file) viene valutato quando lo script bash è valutato, prima che il gatto con redirect viene eseguito.

supponendo che il file che si desidera modificare è my.txt

$cat my.txt    
this is the regular file

E il file che si desidera anteporre è di intestazione

$ cat header
this is the header

Essere sicuri di avere un finale di riga vuota nel file di intestazione.
Ora si può precedere con

$cat header <(cat my.txt) > my.txt

Si finisce con

$ cat my.txt
this is the header
this is the regular file

Per quanto ne so, questo funziona solo in 'bash'.

Quando si avvia cercando di fare cose che diventano difficili in shell-script, vorrei vivamente di guardare in riscrivendo la sceneggiatura in un "vero" linguaggio di scripting (Python/Perl/Ruby/ecc)

Come per precedere da una riga di un file, non è possibile farlo tramite tubazioni, quando si fare una cosa del genere cat blah.txt | grep something > blah.txt, inavvertitamente oscura il file.C'è un piccolo programma di utilità di comando chiamato sponge è possibile installare (si cat blah.txt | grep something | sponge blah.txt e memorizza il contenuto del file, poi lo scrive il file).È simile a un file temp, ma non hanno a che fare, in modo esplicito.ma direi che è un "peggio" requisito che, per esempio, Perl.

Ci può essere un modo per farlo via awk, o simili, ma se devi usare la shell-script, penso che un file temp è di gran lunga il modo più semplice(/solo?) modo..

EDIT:Questa è rotto.Vedere Il comportamento strano quando all'inizio di un file con gatto e tee

La soluzione a sovrascrivere il problema è che utilizza tee:

cat header main | tee main > /dev/null

Come Daniel Velkov suggerisce, utilizzare tee.
Per me, che è di semplice soluzione intelligente:

{ echo foo; cat bar; } | tee bar > /dev/null

Quello che uso io.Questo permette di specificare l'ordine, caratteri supplementari, ecc, in modo che ti piaccia:

echo -e "TEXTFIRSt\n$(< header)\n$(< my.txt)" > my.txt

P. S:solo che non funziona se il file contiene il testo con la barra rovesciata, perche ' viene interpretata come caratteri di escape

Per lo più per divertimento/shell golf, ma

ex -c '0r myheader|x' myfile

farà il trucco, e non ci sono tubazioni o reindirizzamenti.Naturalmente, vi/ex non è realmente interattiva per utilizzare, in modo che vi lampeggia brevemente.

Perché non usare semplicemente il comando ed (come già suggerito da fluffle qui)?

ed legge l'intero file in memoria ed esegue automaticamente un file di modifica!

Così, se il file non è enorme ...

# cf. "Editing files with the ed text editor from scripts.",
# http://wiki.bash-hackers.org/doku.php?id=howto:edit-ed

prepend() {
   printf '%s\n' H 1i "${1}" . wq | ed -s "${2}"
}

echo 'Hello, world!' > myfile
prepend 'line to prepend' myfile

Un'altra soluzione potrebbe essere l'utilizzo di aprire un handle di file come suggerito da Jürgen Hötzel in Reindirizzare l'output di sed 's/c/d/' miofile per myFile

echo cat > manipulate.txt
exec 3<manipulate.txt
# Prevent open file from being truncated:
rm manipulate.txt
sed 's/cat/dog/' <&3 > manipulate.txt

Tutto questo può essere messo su una singola linea, naturalmente.

Una variante cb0 la soluzione per il "no temp file di" anteporre il testo fisso:

echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified ) 

Di nuovo, questo si basa su sub-shell esecuzione - il (..) - per evitare che il gatto rifiuta di avere lo stesso file di input e di output.

Nota:Piaciuto di questa soluzione.Tuttavia, a mio Mac, il file originale viene perso (il pensiero non dovrebbe, ma lo fa).Che potrebbe essere risolto inserendo la tua soluzione:echo "testo anteporre" | cat - file_to_be_modified | cat > tmp_file;mv tmp_file file_to_be_modified

Ecco cosa ho scoperto:

echo -e "header \n$(cat file)" >file
sed -i -e '1rmyheader' -e '1{h;d}' -e '2{x;G}' myfile

AVVISO:questo ha bisogno di un po ' più di lavoro per soddisfare le OP esigenze.

Ci dovrebbe essere un modo per rendere il sed approccio @shixilun lavoro, nonostante la sua perplessità.Ci deve essere un comando bash fuga gli spazi quando la lettura di un file in una sed stringa sostitutiva (ad es.sostituire i caratteri di nuova riga con ' '.I comandi della Shell vis e cat si può trattare con i caratteri non stampabili, ma non gli spazi, in modo che questo non risolverà il por problema:

sed -i -e "1s/^/$(cat file_with_header.txt)/" file_to_be_prepended.txt

non riesce a causa di raw, a capo del sostituto di script, che hanno bisogno di essere preceduto da un carattere di continuazione di riga () e magari seguita da un &, per mantenere la calotta e sed, felice, come questo MODO di rispondere

sed ha un limite di dimensione di 40K per non globale di ricerca-sostituire i comandi (non finale /g per il modello) quindi sarebbe probabilmente evitare la paura di sovraccarico del buffer problemi di awk che anonima ha avvertito della.

sed -i -e "1s/^/new first line\n/" old_file.txt

Con $( comando ) è possibile scrivere l'output di un comando in una variabile.Così ho fatto in tre comandi in una sola riga e nessun file temporaneo.

originalContent=$(cat targetfile) && echo "text to prepend" > targetfile && echo "$originalContent" >> targetfile

Se si dispone di un file di grandi dimensioni (poche centinaia di kilobyte nel mio caso) e l'accesso a python, questo è molto più veloce cat tubo soluzioni:

python -c 'f = "filename"; t = open(f).read(); open(f, "w").write("text to prepend " + t)'

Una soluzione con printf:

new_line='the line you want to add'
target_file='/file you/want to/write to'

printf "%s\n$(cat ${target_file})" "${new_line}" > "${target_file}"

Si potrebbe anche fare:

printf "${new_line}\n$(cat ${target_file})" > "${target_file}"

Ma in quel caso devi essere sicuro che non ci sono % ovunque, compreso il contenuto del file di destinazione, che può essere interpretato e avvitare i tuoi risultati.

È possibile utilizzare perl riga di comando:

perl -i -0777 -pe 's/^/my_header/' tmp

Dove -vado a creare una linea di sostituzione del file e -0777 sarà slurp tutto il file e fare ^ partita solo l'inizio.-pe stampa tutte le righe

O se my_header è un file:

perl -i -0777 -pe 's/^/`cat my_header`/e' tmp

Dove la /e consentirà un eval di codice nella sostituzione.

current=`cat my_file` && echo 'my_string' > my_file && echo $current >> my_file

dove "my_file" è il file di anteporre "my_string" per.

Sto piacimento @fluffle s ed approccio il migliore.Dopo tutto, qualsiasi strumento a riga di comando di interruttori vs script editor comandi sono essenzialmente la stessa cosa qui;non vedendo un script editor soluzione "pulizia" sia minore o quant'altro.

Ecco la mia one-liner aggiunto .git/hooks/prepare-commit-msg anteporre un repo .gitmessage file di messaggi di commit:

echo -e "1r $PWD/.gitmessage\n.\nw" | ed -s "$1"

Esempio .gitmessage:

# Commit message formatting samples:
#       runlevels: boot +consolekit -zfs-fuse
#

Sto facendo 1r invece di 0r, perché , che lascerà il vuoto pronto per scrivere la linea sulla parte superiore del file del template originale.Non inserire una riga vuota sopra il tuo .gitmessage quindi, si finirà con due righe vuote. -s sopprime informazioni di diagnostica di uscita di ed.

In connessione con l'andare attraverso questo, ho scoperto che per vim-appassionati è bene, inoltre, sono:

[core]
        editor = vim -c ':normal gg'

variabili, ftw?

NEWFILE=$(echo deb http://mirror.csesoc.unsw.edu.au/ubuntu/ $(lsb_release -cs) main universe restricted multiverse && cat /etc/apt/sources.list)
echo "$NEWFILE" | sudo tee /etc/apt/sources.list

Penso che questo è il più pulito variazione di ed:

cat myheader | { echo '0a'; cat ; echo -e ".\nw";} | ed myfile

come una funzione:

function prepend() { { echo '0a'; cat ; echo -e ".\nw";} | ed $1; }

cat myheader | prepend myfile

Se sei di scripting in BASH, in realtà, si può solo problema:

cat - yourfile  /tmp/out && mv /tmp/out yourfile

Che in realtà è nel Complesso Esempio te postato nella tua domanda.

IMHO non c'è shell soluzione (e non sarà mai) che opera in modo coerente e affidabile, indipendentemente dalle dimensioni dei due file myheader e myfile.La ragione è che se si vuole fare senza ricorrere a un file temporaneo (e senza che il guscio si ripresenterà in silenzio in un file temporaneo, ad es.attraverso costrutti exec 3<>myfile, tubazioni per tee, etc.

La "vera" soluzione che stai cercando esigenze di giocherellare con il filesystem, e quindi non è disponibile in userspace e sarebbe dipendente dalla piattaforma:si chiede di modificare il filesystem puntatore in uso da myfile per il valore corrente del filesystem puntatore per myheader e sostituire il file system il EOF di myheader con una incatenato link per il filesystem corrente indirizzo puntato da myfile.Questo non è banale e, ovviamente, non può essere fatto da un non-superuser, e forse non è il superuser sia...Giocare con gli inode, etc.

Si può più o meno falsi utilizzando dispositivi di loop, però.Si veda per esempio questo thread COSÌ.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top