É possível adicionar algum texto no início de um arquivo na CLI sem fazer novo arquivo?

1

Eu tenho dois arquivos; file1 contendo -

hello world
hello bangladesh  

e file2 contendo -

 Dhaka in Bangladesh
 Dhaka is capital of Bangladesh  

Desejo atualizar file2 como -

hello world
hello bangladesh 
Dhaka in Bangladesh
Dhaka is capital of Bangladesh

Isso é feito por -

cat file1 file2 >> file3
mv file3 file2  

Mas não quero criar um novo arquivo. Eu acho que usando sed pode ser possível.

    
por alhelal 03.01.2018 / 02:20

4 respostas

4

Claro que é possível.

(A menos que você também esteja preocupado com a possibilidade de arquivos temporários serem criados "por dentro", como praticamente todos os editores de texto trabalham dessa maneira. Eu não digo que é totalmente impossível evitar qualquer possibilidade capa temp criação de arquivo, mas não é coberto nesta resposta.)

printf '%s\n' '0r file1' x | ex file2

Este é um comando compatível com POSIX que usa ex , o predecessor não visual especificado pelo POSIX para vi .

printf é usado apenas aqui para alimentar um comando para o editor. Que printf de saídas é:

0r file1
x

x é salvar e sair.

r é "lido no conteúdo do arquivo nomeado."

0 especifica o número da linha após o qual o texto lido deve ser colocado.

    
por 03.01.2018 / 02:26
3

Não há muitas maneiras de modificar arquivos usando ferramentas padrão. Mesmo que pareçam fazer isso, eles podem estar usando arquivos temporários (por exemplo, GNU sed -i ).

ex , por outro lado, fará o truque:

 ex -n -c '0r file2' -c wq file1

ex é um editor de linhas e vim evoluiu para que esses comandos pareçam familiares. 0r filename faz o mesmo que :0r filename in vim : insira o arquivo especificado após o endereço fornecido (número da linha). O número da linha aqui é 0, que é um tipo de linha virtual que representa a linha antes da linha 1. Assim, o arquivo será inserido antes de qualquer texto existente.

Em seguida, temos wq , que salva e sai.

Se você notar o comentário abaixo sobre isso ser "muito frágil", leve-o com um grão de sal. Se você quiser usar isso em um script, certifique-se de fazer a validação correta de pré-condição (existem arquivos, são legíveis / graváveis, etc.). Bons roteiristas estariam fazendo isso de qualquer maneira.

Atualização: adicionei -n para tratar das preocupações do OP sobre evitar qualquer criação de arquivo temporário. Supondo que seu ex seja implementado como parte de vim (como é o caso na maioria dos sistemas modernos), esse sinalizador suprimirá a criação do arquivo de permuta normal que vim faz.

    
por 03.01.2018 / 02:28
0
all=$( cat file1 file2 )
echo "$all" > file2

só funciona com arquivos pequenos.

    
por 03.01.2018 / 06:44
0

Semelhante à resposta de Jasen, esta é uma base para um utilitário.

O código esponja no pacote moreutils foi projetado para permitir uma capacidade in-loco para quase qualquer programa, embora externamente. Essencialmente, ele absorve a entrada de STDIN e, em seguida, grava a saída coletada em um nome de arquivo, mas NÃO com a reorientação.

Gostamos da ideia, por isso criamos uma obra semelhante que coleta dados na memória, em oposição a um arquivo como a esponja real.

Aqui está um trecho de script de shell para ilustrar isso:

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }

pl " Input files data2, data3:"
head data[23]
pe
ls -gGli data[23]

pl " Results, re-write file from memory, preserving inode:"
cat data[23] | ./absorb-memory-public data3
head -v data3
pe
ls -gGli data3

Produção:

-----
 Input files data2, data3:
==> data2 <==
hello world
hello bangladesh 

==> data3 <==
Dhaka in Bangladesh
Dhaka is capital of Bangladesh  

1051395 -rw-r--r-- 1 30 Jan  7 08:58 data2
1052221 -rw-r--r-- 1 53 Jan  7 08:58 data3

-----
 Results, re-write file from memory, preserving inode:
==> data3 <==
hello world
hello bangladesh 
Dhaka in Bangladesh
Dhaka is capital of Bangladesh  

1052221 -rw-r--r-- 1 83 Jan  7 08:58 data3

O núcleo do código perl é bastante curto (especialmente sem verificação de erros, cuja adição pode ser desejável):

use warnings;
use strict;
use Carp;

# Avoid hang for argument matching "-version","--version", etc.
exit(0) if @ARGV && $ARGV[0] =~ /-version/;

my ( $file, $f, $memory );
$file = shift || croak("Need a filename.");

$/ = 0777;      # Slurp the entire STDIN
$memory = do { local $/; <> };

open( $f, ">", $file ) || die " Cannot open file \"$file\" for write.\n";

print $f "$memory";

Executar em um sistema como:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30
perl 5.20.2

Felicidades ... felicidades, drl

    
por 07.01.2018 / 16:04