Como inserir um texto no início de um arquivo?

213

Até agora, consegui descobrir como adicionar uma linha no início de um arquivo, mas não é exatamente isso que desejo. Mostrarei em um exemplo

Conteúdo do arquivo

some text at the beginning

Resultado

<added text> some text at the beginning

É semelhante, mas não quero criar nenhuma nova linha com ela ...

Eu gostaria de fazer isso com sedse possível.

user219882
fonte
Alguma coisa aqui funciona para você? stackoverflow.com/questions/54365/… - você não precisa usar sed.
Wkl

Respostas:

314

sed pode operar em um endereço:

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

O que é isso mágico que 1svocê vê em todas as respostas aqui? Endereçamento de linha! .

Deseja adicionar <added text>as 10 primeiras linhas?

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

Ou você pode usar Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}
kev
fonte
67
Para realmente inserir uma nova linha: sed -i '1s / ^ / <texto adicionado> \ n /' arquivo
jslatts
1
Por que usar -i ?? No homem, diz que é para sufixo. linux.die.net/man/1/sed
endrigoantonini 15/05
-i significa in-loco, você pode anexar um sufixo a -i para fazer uma cópia em vez de sobrescrever. -i.new criaria um novo arquivo terminado em .new, mas apenas -i editaria o arquivo diretamente.
Jay Kamat
3
Observe que o sed não funcionará em um arquivo vazio - não é possível fazer com que o sed afaict faça nada com entradas de tamanho 0.
Jtill # 5/15
2
A falha desta solução é que ela não adiciona o texto se o arquivo estiver vazio.
precisa saber é o seguinte
41

Se você deseja adicionar uma linha no início de um arquivo, é necessário adicionar \nno final da string a melhor solução acima.

A melhor solução adicionará a string, mas com a string, ela não adicionará uma linha no final de um arquivo.

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

Se o arquivo tiver apenas uma linha, você poderá usar:

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

Se for mais de uma linha. um de:

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

Eu incluí o último para que você saiba como fazer intervalos de linhas. Ambos "substituem" o marcador da linha inicial nas linhas afetadas pelo texto que você deseja inserir. Você também pode (supondo que você sedseja moderno o suficiente) usar:

sed -i 'whatever command you choose' filename

para editar no local.

paxdiablo
fonte
11

Você pode usar cat -

printf '%s' "some text at the beginning" | cat - filename
Lex
fonte
6
Isso produziria apenas o texto seguido pelo conteúdo do arquivo, mas não modifica o arquivo.
Adaephon
Essa é uma boa solução, eu me pergunto por que não recebeu nenhum voto positivo. Aqui está o meu, meu bom senhor. Além disso, por que printf e não um eco simples?
ychaouche
1
@ychaouche - presumivelmente porque não há uma maneira portátil de impedir a echoadição de uma nova linha?
Toby Speight
Eu tentei dirigir isso em um arquivo anexando > fileao comando, ele jus spam meu terminal com"some text at the beginning"
theonlygusti
2
printf '%s' "some text" | cat - filename > tmpfile && mv tmpfile filename
luca
10

Para inserir apenas uma nova linha:

sed '1i\\'

fonte
8

Usar subshell:

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

Observe que, no OS X sed -i <pattern> file,, falha. No entanto, se você fornecer uma extensão de backup sed -i old <pattern> file, ele fileserá modificado no local enquanto file.oldé criado. Você pode excluir file.oldno seu script.

Curt Clifton
fonte
4
Ou arquivo sed -i ''. Depois, basta editar no local e não fazer backups.
Harv
Descobri que o macOS sed deseja editar um ponto sem criar um backup: sed -i. Arquivo <pattern>
Bryan
4

PROBLEMA: marque um arquivo, na parte superior do arquivo, com o nome base do diretório pai.

Ou seja, para

/mnt/Vancouver/Programming/file1

marque a parte superior file1 com Programming.

SOLUÇÃO 1 - arquivos não vazios:

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

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

1s coloca o texto na linha 1 do arquivo.

SOLUÇÃO 2 - arquivos vazios ou não vazios:

O sedcomando acima falha em arquivos vazios. Aqui está uma solução, com base em /superuser/246837/how-do-i-adad-text-to-the-beginning-of-a-file-in-bash/246841#246841

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

Observe que o -comando in no cat é necessário (lê a entrada padrão: consulte man catpara obter mais informações). Aqui, acredito, é necessário pegar a saída da instrução printf (para STDIN) e colocar isso e o arquivo em temp ... Veja também a explicação na parte inferior de http://www.linfo.org/cat .html .

Também adicionei -fao mvcomando, para evitar solicitações de confirmação ao substituir arquivos.

Para recursar em um diretório:

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

Observe também que isso quebrará caminhos com espaços; existem soluções em outros lugares (por exemplo, globbing de arquivos ou find . -type f ...soluções de tipo) para elas.

ADENDO: Re: meu último comentário, este script permitirá que você repasse sobre diretórios com espaços nos caminhos:

#!/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
fonte
3

Olá com retorno de carro:

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

Para adicionar uma linha na parte superior do arquivo:

sed -i '1iText to add\'
solidsnack
fonte
Isso inclui uma nova linha, que o interlocutor não deseja explicitamente.
precisa
Obrigado por me dar exatamente o que eu preciso
FindOutIslamNow
3

Existe uma maneira muito fácil:

echo "your header" > headerFile.txt
cat yourFile >> headerFile.txt
Raphael Villas Boas
fonte
Ow ... desculpe, agora que percebi que você queria adicionar no início e não uma nova linha.
Raphael Villas Boas
Mas eu queria uma nova linha. Então, obrigado pela abordagem simplista.
TheSatinKnight
3

Apenas por diversão, aqui está uma solução edque não tem o problema de não funcionar em um arquivo vazio. Você pode colocá-lo em um script de shell como qualquer outra resposta a esta pergunta.

ed Test <<EOF
a

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

O script acima adiciona o texto a ser inserido na primeira linha e, em seguida, une a primeira e a segunda linha. Para evitar a saída por erro com uma associação inválida, ele primeiro cria uma linha em branco no final do arquivo e a remove mais tarde, se ainda existir.

Limitações: Este script não funciona se <added text>for exatamente igual a um único período.

merlin2011
fonte
2

meus dois centavos:

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

Isso funcionará mesmo se a string contiver barra "/"

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

A primeira taccanaliza o arquivo para trás (última linha primeiro), para que o "texto a inserir" apareça por último. O segundo o tacenvolve novamente para que a linha inserida esteja no início e o arquivo original esteja em sua ordem original.

paulp
fonte
1
Você pode explicar como isso ajudaria o Tomas com o problema?
John Odom
tac | tac - que é como mentalidades não escalável formar :-(
Michael Shigorin
0

Outra solução com aliases. Adicione ao seu arquivo 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"
0x8BADF00D
fonte