Come inserire un testo all'inizio di un file?


213

Finora sono stato in grado di trovare come aggiungere una riga all'inizio di un file, ma non è esattamente quello che voglio. Lo mostrerò su un esempio

Contenuto del file

some text at the beginning

Risultato

<added text> some text at the beginning

È simile ma non voglio creare alcuna nuova linea con esso ...

Mi piacerebbe farlo con sedse possibile.


Qualcosa qui funziona per te? stackoverflow.com/questions/54365/… - non è necessario utilizzarlo sed.
WKL

Risposte:


314

sed può operare su un indirizzo:

$ sed -i '1s/^/<added text> /' file

Cos'è questo magico 1sche vedi su ogni risposta qui? Indirizzamento di linea! .

Vuoi aggiungere <added text>sulle prime 10 righe?

$ sed -i '1,10s/^/<added text> /' file

Oppure puoi usare Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}

67
Per inserire effettivamente una nuova riga: sed -i '1s / ^ / <testo aggiunto> \ n /' file
jslatts

1
Perché usare -i ?? Sull'uomo dice che è per il suffisso. linux.die.net/man/1/sed
endrigoantonini

-i significa sul posto, è possibile aggiungere un suffisso a -i per creare una copia anziché sovrascriverla. -i.new creerebbe un nuovo file che termina con .new, ma solo -i modificherà direttamente il file.
Jay Kamat,

3
Nota che sed non funzionerà su un file vuoto - afaict sed non può essere fatto per fare nulla con input di lunghezza 0.
jillill

2
Il difetto di questa soluzione è che non aggiunge il testo se il file è vuoto.
DBedrenko,

41

Se si desidera aggiungere una riga all'inizio di un file, è necessario aggiungere \nalla fine della stringa nella migliore soluzione sopra.

La soluzione migliore aggiungerà la stringa, ma con la stringa non aggiungerà una riga alla fine di un file.

sed -i '1s/^/your text\n/' file

27

Se il file è solo una riga, è possibile utilizzare:

sed 's/^/insert this /' oldfile > newfile

Se è più di una riga. uno di:

sed '1s/^/insert this /' oldfile > newfile
sed '1,1s/^/insert this /' oldfile > newfile

Ho incluso quest'ultimo in modo che tu sappia come fare intervalli di linee. Entrambi "sostituiscono" l'indicatore della linea di partenza sulle linee interessate con il testo che si desidera inserire. Puoi anche (supponendo che tu sedsia abbastanza moderno) usare:

sed -i 'whatever command you choose' filename

per eseguire modifiche sul posto.


11

Puoi usare cat -

printf '%s' "some text at the beginning" | cat - filename

6
Ciò produrrebbe solo il testo seguito dal contenuto del file, ma non modificherà affatto il file.
Adaephon,

È una buona soluzione, mi chiedo perché non abbia ricevuto alcun voto. Ecco il mio buon signore. Inoltre, perché printf e non una semplice eco?
ychaouche,

1
@ychaouche - presumibilmente perché non esiste un modo portatile per impedire l' echoaggiunta di una nuova riga?
Toby Speight,

Ho provato a dirigerlo in un file aggiungendo > fileil comando, con cui ho spammato il mio terminale con"some text at the beginning"
theonlygusti,

2
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
luca,

11

Per inserire solo una nuova riga:

sed '1i\\'

Mi chiedo perché le risposte più votate vengano usate da tutti invece di i. Qualche svantaggio di questo?
Cesare

8

Usa subshell:

echo "$(echo -n 'hello'; cat filename)" > filename

5

Si noti che su OS X sed -i <pattern> file, non riesce. Tuttavia, se si fornisce un'estensione di backup sed -i old <pattern> file, fileviene modificato in posizione mentre file.oldviene creato. È quindi possibile eliminare file.oldnel tuo script.


4
O sed -i '' file. Quindi modificherà sul posto e non eseguirà i backup.
Harv,

Ho scoperto che macOS sed vuole un punto da modificare sul posto senza creare un backup: sed -i. File <pattern>
Bryan

4

PROBLEMA: taggare un file, nella parte superiore del file, con il nome di base della directory principale.

Vale a dire, per

/mnt/Vancouver/Programming/file1

tagga la cima file1con Programming.

SOLUZIONE 1 - file non vuoti:

bn=${PWD##*/}    ## bn: basename

sed -i '1s/^/'"$bn"'\n/' <file>

1s posiziona il testo alla riga 1 del file.

SOLUZIONE 2 - file vuoti o non vuoti:

Il sedcomando sopra riportato non riesce su file vuoti. Ecco una soluzione, basata su /superuser/246837/how-do-i-add-text-to-the-beginning-of-a-file-in-bash/246841#246841

printf "${PWD##*/}\n" | cat - <file> > temp && mv -f temp <file>

Si noti che -è richiesto il comando in the cat (legge l'input standard: vedere man catper ulteriori informazioni). Qui, credo, è necessario portare l'output dell'istruzione printf (su STDIN), e cat che e il file su temp ... Vedi anche la spiegazione in fondo a http://www.linfo.org/cat .html .

Ho anche aggiunto -fal mvcomando, per evitare di essere chiesto conferme quando si sovrascrivono i file.

Per ricorrere su una directory:

for file in *; do printf "${PWD##*/}\n" | cat - $file > temp && mv -f temp $file; done

Si noti inoltre che questo interromperà i percorsi con spazi; ci sono soluzioni, altrove (ad es. file globbing o find . -type f ...soluzioni di tipo) per quelle.

ADDENDUM: Ri: il mio ultimo commento, questo script ti permetterà di ricorrere alle directory con spazi nei percorsi:

#!/bin/bash

## /programming/4638874/how-to-loop-through-a-directory-recursively-to-delete-files-with-certain-extensi

## To allow spaces in filenames,
##   at the top of the script include: IFS=$'\n'; set -f
##   at the end of the script include: unset IFS; set +f

IFS=$'\n'; set -f

# ----------------------------------------------------------------------------
# SET PATHS:

IN="/mnt/Vancouver/Programming/data/claws-test/corpus test/"

# /superuser/716001/how-can-i-get-files-with-numeric-names-using-ls-command

# FILES=$(find $IN -type f -regex ".*/[0-9]*")        ## recursive; numeric filenames only
FILES=$(find $IN -type f -regex ".*/[0-9 ]*")         ## recursive; numeric filenames only (may include spaces)

# echo '$FILES:'                                      ## single-quoted, (literally) prints: $FILES:
# echo "$FILES"                                       ## double-quoted, prints path/, filename (one per line)

# ----------------------------------------------------------------------------
# MAIN LOOP:

for f in $FILES
do

  # Tag top of file with basename of current dir:
  printf "[top] Tag: ${PWD##*/}\n\n" | cat - $f > temp && mv -f temp $f

  # Tag bottom of file with basename of current dir:
  printf "\n[bottom] Tag: ${PWD##*/}\n" >> $f
done

unset IFS; set +f

3

Ciao con ritorno a capo:

sed -i '1s/^/your text\n/' file

3

Per aggiungere una riga nella parte superiore del file:

sed -i '1iText to add\'

Ciò include una nuova riga, che l'interrogante non vuole esplicitamente.
Toby Speight,

Grazie per avermi dato esattamente ciò di cui ho bisogno
FindOutIslamNow

3

C'è un modo molto semplice:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt

Ow ... scusa, ora che mi rendo conto che volevi aggiungere all'inizio e non una nuova riga.
Raphael Villas Boas,

Ma io volevo una nuova linea. Quindi grazie per l'approccio semplicistico.
TheSatinKnight

3

Solo per divertimento, ecco una soluzione edche non ha il problema di non lavorare su un file vuoto. Puoi inserirlo in uno script di shell come qualsiasi altra risposta a questa domanda.

ed Test <<EOF
a

.
0i
<added text>
.
1,+1 j
$ g/^$/d
wq
EOF

Lo script sopra aggiunge il testo da inserire nella prima riga, quindi unisce la prima e la seconda riga. Per evitare la chiusura in caso di errore con un join non valido, crea prima una riga vuota alla fine del file e rimuoverlo in seguito se esiste ancora.

Limitazioni: questo script non funziona se <added text>è esattamente uguale a un singolo punto.


2

i miei due centesimi:

sed  -i '1i /path/of/file.sh' filename

Funzionerà anche se la stringa contiene barra "/"


1
echo -n "text to insert " ;tac filename.txt| tac > newfilename.txt

Il primo tacconvoglia il file all'indietro (prima l'ultima riga) in modo che il "testo da inserire" appaia per ultimo. Il 2 lo tacavvolge di nuovo in modo che la riga inserita sia all'inizio e il file originale sia nell'ordine originale.


1
Puoi per favore spiegare come ciò aiuterebbe Tomas a risolvere il problema?
John Odom,

tac | tac: ecco come si formano le mentalità non scalabili :-(
Michael Shigorin,

0

Un'altra soluzione con alias. Aggiungi al tuo file init rc / env:

addtail () { find . -type f ! -path "./.git/*" -exec sh -c "echo $@ >> {}" \; }
addhead () { find . -type f ! -path "./.git/*" -exec sh -c  "sed -i '1s/^/$@\n/' {}" \; }

Uso:

addtail "string to add at the beginning of file"
addtail "string to add at the end of file"
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.