Questão Como faço para adicionar texto ao início de um arquivo no Bash?


Oi eu quero preceder o texto para um arquivo. Por exemplo, quero adicionar tarefas ao início de um arquivo todo.txt. Estou ciente echo 'task goes here' >> todo.txt mas isso adiciona a linha ao final do arquivo (não o que eu quero).


228


origem


Não há uma maneira eficiente de fazer isso para arquivos grandes: unix.stackexchange.com/questions/87772/… - Ciro Santilli 新疆改造中心 六四事件 法轮功


Respostas:


echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

ou

sed -i '1s/^/task goes here\n/' todo.txt

ou

sed -i '1itask goes here' todo.txt

304



o primeiro funciona muito bem! você se importaria de explicar a lógica? Não estou particularmente certo de como interpretar a sintaxe. - user479534
@ user8347: Tubulação (|) a mensagem (echo '...') para cat que usa - (entrada padrão) como o primeiro arquivo e todo.txtcomo o segundo. cat CONCATa vários arquivos. Envie a saída (>) para um arquivo chamado temp. Se não houver erros (&&) a partir de cat então renomeie (mv) a temp arquivo de volta para o arquivo original (todo.txt). - Dennis Williamson
Eu não sabia sobre essa sintaxe possível no último exemplo do sed, alguém pode me dizer qual é o nome desse tipo de sintaxe para que eu possa pesquisar mais sobre isso? - Kira
@ Kira: O 1 significa fazer o próximo comando apenas na linha um do arquivo e o i comando é inserir. Procure na página man sob a seção "Addresses" e na seção "Zero-or One-address commands". - Dennis Williamson
@Terrance: Se o seu sed comando é algo como isto (inserindo uma guia principal): '1i\tSome Text', você pode precisar dobrar a barra invertida. Caso contrário, seu dialeto de sed pode não reconhecer \t como guia. - Dennis Williamson


Uma opção mais simples na minha opinião é:

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

Isso funciona porque o comando dentro de $(...) é executado antes todo.txt é sobrescrito com > todo.txt

Enquanto as outras respostas funcionam bem, acho isso muito mais fácil de lembrar, porque eu uso eco e gato todos os dias.

EDITAR: Esta solução é uma péssima ideia se houver alguma barra invertida todo.txtporque graças ao -e O eco da bandeira irá interpretá-los. Outra maneira muito mais fácil de obter novas linhas na string de prefácio é ...

echo "task goes here
$(cat todo.txt)" > todo.txt

... simplesmente para usar novas linhas. Claro, não é mais uma linha de uma linha, mas, na verdade, também não era uma linha direta. Se você estiver fazendo isso dentro de um script e estiver preocupado com o recuo (por exemplo, se estiver executando isso dentro de uma função), há algumas soluções alternativas para fazer isso ainda se encaixar bem, incluindo, mas não se limitando a:

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

Além disso, se você se importa se uma nova linha é adicionada ao final de todo.txtnão use isso. Bem, exceto o penúltimo. Isso não atrapalha com o final.


59



Eu não recebo $ (...) executado. - SCL
Isso pode funcionar melhor (ou nada) com aspas duplas em vez de simples… - ℝaphink
Não vai o -e também converter seqüências de escape dentro todo.txt? - mk12
Soluções alternativas yield -> cat: <destination filename>: o arquivo de entrada é o arquivo de saída ... - ingyhere
printf seria muito mais consistente em todas as plataformas e geralmente deveria funcionar mais suavemente do que echo -e - Peter Berg


o moreutils tem uma boa ferramenta chamada sponge:

echo "task goes here" | cat - todo.txt | sponge todo.txt

Ele "absorverá" STDIN e, em seguida, gravará no arquivo, o que significa que você não precisa se preocupar com arquivos temporários e movê-los.

Você pode ter moreutils com muitas distribuições do Linux, apt-get install moreutils, ou no OS X usando Homebrewcom brew install moreutils.


26





Você pode usar o Vim no modo Ex:

ex -sc '1i|task goes here' -cx todo.txt
  1. 1 selecione a primeira linha

  2. i inserir

  3. x salvar e fechar


5





Você pode criar um novo arquivo temporário.

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

Você também pode usar sed ou awk. Mas basicamente a mesma coisa acontece.


3



Diga que você está sem espaço em disco para que new_todo.txt fica escrito apenas parcialmente. Sua solução parece perder o arquivo original. - NPE
Quem fica sem espaço em disco? ;-) É apenas um exemplo simples. - Keith
@ Keith Alguém trabalhando em uma VM que não esperava precisar de uma unidade virtual particularmente grande. Ou alguém movendo um arquivo grande. Em qualquer caso, o argumento real contra isso é permissões de diretório; se você não tem permissão para criar novos arquivos no diretório fornecido, o único comando que será executado com sucesso no seu script é o rm do arquivo original. - Parthian Shot


Se o arquivo de texto for pequeno o suficiente para caber na memória, você não precisará criar um arquivo temporário para substituí-lo. Você pode carregar tudo na memória e escrevê-lo de volta no arquivo.

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

É impossível adicionar linhas ao início do arquivo sem gravar o arquivo inteiro.


3



Apenas para fazer a pergunta óbvia: Onde está o limite de caracteres das variáveis ​​da shell? - nixda
Tanto quanto eu sei, é limitado apenas pela quantidade de memória disponível. Eu preenchi variáveis ​​bem acima de 100MB na memória. text=$(cat file). Tenha cuidado para usar apenas o texto, porque as variáveis ​​do shell não são binárias mywiki.wooledge.org/BashFAQ/058 - Rucent88


Você não pode inserir conteúdo no início de um arquivo. A única coisa que você pode fazer é substituir o conteúdo existente ou anexar bytes após o término atual do arquivo.

Qualquer solução para sua pergunta, em seguida, requer um arquivo temporário (ou buffer) para ser criado (na memória ou no disco), que acabará por substituir o arquivo original.

Cuidado para não perder dados preservando o arquivo original enquanto cria o novo, caso o sistema de arquivos esteja cheio durante o processo. por exemplo:

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

2



Downvoters são bem-vindos para explicar sua motivação. Nenhuma das respostas restantes, incluindo a aceita, contradiz qualquer coisa na minha resposta. - jlliagre
Isso é difícil de analisar como o <...> pareçam com colchetes, o que eu suponho que eles não são. Um espaço entre o <e o (pode ajudar? - dumbledad
Isso não está funcionando para mim. echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile' funciona mas cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile' dá o erro "echo: Nenhum tal arquivo ou diretório" - dumbledad
@dumbledad Você está pensando demais na minha resposta. Não há nada para você analisar. Um espaço entre o < e a ( iria quebrar a sintaxe. Experimentar cat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile' - jlliagre