Comment insérer un texte au début d'un fichier?

213

Jusqu'à présent, j'ai pu trouver comment ajouter une ligne au début d'un fichier, mais ce n'est pas exactement ce que je veux. Je vais le montrer sur un exemple

Contenu du fichier

some text at the beginning

Résultat

<added text> some text at the beginning

C'est similaire mais je ne veux pas créer de nouvelle ligne avec ça ...

Je voudrais le faire avec sedsi possible.

user219882
la source
Quelque chose ici vous convient? stackoverflow.com/questions/54365/… - vous n'avez pas besoin d'utiliser sed.
wkl

Réponses:

314

sed peut fonctionner sur une adresse:

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

Quelle est cette magie que 1svous voyez sur chaque réponse ici? Adressage de ligne! .

Vous souhaitez ajouter <added text>sur les 10 premières lignes?

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

Ou vous pouvez utiliser Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}
kev
la source
67
Pour insérer réellement une nouvelle ligne: sed -i '1s / ^ / <texte ajouté> \ n /' fichier
jslatts
1
Pourquoi utiliser -i ?? Sur l'homme, il dit que c'est pour le suffixe. linux.die.net/man/1/sed
endrigoantonini
-i signifie in-place, vous pouvez ajouter un suffixe à -i pour faire une copie plutôt que l'écraser. -i.new créerait un nouveau fichier se terminant par .new, mais juste -i modifierait le fichier directement.
Jay Kamat
3
Notez que sed ne fonctionnera pas sur un fichier vide - afaict sed ne peut rien faire du tout avec une entrée de longueur 0.
2015
2
L'inconvénient de cette solution est qu'elle n'ajoute pas le texte si le fichier est vide.
DBedrenko
41

Si vous souhaitez ajouter une ligne au début d'un fichier, vous devez l'ajouter \nà la fin de la chaîne dans la meilleure solution ci-dessus.

La meilleure solution ajoutera la chaîne, mais avec la chaîne, elle n'ajoutera pas de ligne à la fin d'un fichier.

sed -i '1s/^/your text\n/' file
Ali Reza Ebadat
la source
27

Si le fichier est composé d'une seule ligne, vous pouvez utiliser:

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

S'il s'agit de plusieurs lignes. un des:

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

J'ai inclus ce dernier pour que vous sachiez comment faire des gammes de lignes. Ces deux «remplacer» le marqueur de ligne de départ sur leurs lignes affectées par le texte que vous souhaitez insérer. Vous pouvez également (en supposant que votre version sedsoit suffisamment moderne) utiliser:

sed -i 'whatever command you choose' filename

pour effectuer une modification sur place.

paxdiablo
la source
11

Vous pouvez utiliser cat -

printf '%s' "some text at the beginning" | cat - filename
Lex
la source
6
Cela ne produirait que le texte suivi du contenu du fichier, mais cela ne modifie pas du tout le fichier.
Adaephon
C'est une bonne solution, je me demande pourquoi il n'a reçu aucun vote positif. Voici le mien mon bon monsieur. Aussi, pourquoi printf et pas un simple écho?
ychaouche
1
@ychaouche - probablement parce qu'il n'y a aucun moyen portable d'empêcher l' echoajout d'une nouvelle ligne?
Toby Speight
J'ai essayé de diriger cela dans un fichier en ajoutant > fileà la commande, il a spammé mon terminal avec"some text at the beginning"
theonlygusti
2
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
luca
11

Pour insérer juste une nouvelle ligne:

sed '1i\\'

la source
Je me demande pourquoi les réponses les plus votées utilisent toutes s au lieu de i. Des inconvénients à cela?
César
8

Utiliser un sous-shell:

echo "$(echo -n 'hello'; cat filename)" > filename
Nick Roz
la source
5

Notez que sous OS X,, sed -i <pattern> fileéchoue. Cependant, si vous fournissez une extension de sauvegarde,, est sed -i old <pattern> filealors filemodifié en place lors de sa file.oldcréation. Vous pouvez ensuite supprimer file.olddans votre script.

Curt Clifton
la source
4
Ou fichier sed -i ''. Ensuite, il suffit de modifier sur place et de ne pas faire de sauvegardes.
Harv
J'ai trouvé que macOS sed voulait qu'un point soit édité sur place sans créer de sauvegarde: sed -i. Fichier <pattern>
Bryan
4

PROBLÈME: balisez un fichier, en haut du fichier, avec le nom de base du répertoire parent.

C'est-à-dire, pour

/mnt/Vancouver/Programming/file1

balisez le haut de file1avec Programming.

SOLUTION 1 - fichiers non vides:

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

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

1s place le texte à la ligne 1 du fichier.

SOLUTION 2 - fichiers vides ou non vides:

La sedcommande ci-dessus échoue sur les fichiers vides. Voici une solution, basée sur /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>

Notez que la -commande in the cat est obligatoire (lit l'entrée standard: voir man catpour plus d'informations). Ici, je crois, il faut prendre la sortie de l'instruction printf (vers STDIN), et cat ça et le fichier à temp ... Voir aussi l'explication au bas de http://www.linfo.org/cat .html .

J'ai également ajouté -fà la mvcommande, pour éviter qu'on me demande des confirmations lors du remplacement des fichiers.

Pour récapituler sur un répertoire:

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

Notez également que cela rompra les chemins avec des espaces; il existe des solutions ailleurs (par exemple, globalisation de fichiers ou find . -type f ...solutions de type) pour celles-ci.

ADDENDA: Re: mon dernier commentaire, ce script va vous permettre de récursivement sur des répertoires avec des espaces dans les chemins:

#!/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
Victoria Stuart
la source
3

Salut avec retour chariot:

sed -i '1s/^/your text\n/' file
xck
la source
3

Pour ajouter une ligne en haut du fichier:

sed -i '1iText to add\'
solidsnack
la source
Cela inclut une nouvelle ligne, ce que l'interrogateur ne veut pas explicitement.
Toby Speight
Merci de m'avoir donné exactement ce dont j'ai besoin
FindOutIslamNow
3

Il existe un moyen très simple:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt
Raphael Villas Boas
la source
Ow ... désolé, maintenant que je me rends compte que vous vouliez ajouter au début et pas une nouvelle ligne.
Raphael Villas Boas
Mais je voulais une nouvelle ligne. Merci donc pour l'approche simpliste.
TheSatinKnight
3

Juste pour le plaisir, voici une solution utilisant edqui n'a pas le problème de ne pas travailler sur un fichier vide. Vous pouvez le mettre dans un script shell comme n'importe quelle autre réponse à cette question.

ed Test <<EOF
a

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

Le script ci-dessus ajoute le texte à insérer à la première ligne, puis joint la première et la deuxième ligne. Pour éviter que ed ne se termine en cas d'erreur avec une jointure non valide, il crée d'abord une ligne vierge à la fin du fichier et la supprime plus tard si elle existe toujours.

Limitations: ce script ne fonctionne pas s'il <added text>est exactement égal à une seule période.

merlin2011
la source
2

mes deux centimes:

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

Cela fonctionnera même si la chaîne contient une barre oblique "/"

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

Le premier taccanalise le fichier vers l'arrière (dernière ligne en premier) de sorte que le "texte à insérer" apparaît en dernier. Le 2e le tacretourne à la ligne afin que la ligne insérée soit au début et que le fichier d'origine soit dans son ordre d'origine.

paulp
la source
1
Pouvez-vous expliquer comment cela pourrait aider Tomas à résoudre le problème?
John Odom
tac | tac - c'est ainsi que se forment les mentalités non évolutives :-(
Michael Shigorin
0

Une autre solution avec des alias. Ajoutez à votre fichier 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/' {}" \; }

Usage:

addtail "string to add at the beginning of file"
addtail "string to add at the end of file"
0x8BADF00D
la source