OVH Cloud OVH Cloud

Manipulation de fichiers

16 réponses
Avatar
Ph. Chantry
Bonjour,

Je voudrais ajouter des lignes au début d'un fichier.
Sauriez-vous comment faire sans passer par un fichier intermédiaire ?

Par exemple, si les lignes d'en-tête sont dans un fichier A, que je veux
insérer au début du fichier B, je voudrais pouvoir éviter de travailler
ainsi:

# cat A B > C
# mv C B

car cette façon de faire nécessite un espace disponible sur le disque égal à
volume de A + volume de B.

Je voudrais donc une commande qui permette de faire l'équivalent de :

# cat A B > B

Peut-être quelqu'un a-t-il déjà développé ça ?

Merci d'avance,
Philippe

6 réponses

1 2
Avatar
Ph. Chantry
Attention c'est du QND (Quic 'n dirty) et j'ai pas faits de tests
intensifs)


JM


#include <stdio.h>

main( int argc, char **argv)


Ben c'est sympa, ça ! Je n'ai pas eu le temps de répondre "oui" que le code
est déjà pondu !

Les premiers tests ne sont hélas pas conluants:

# cat A
a
# cat B
b
b
b
# ./a.out A B
# cat B
a
b
b


#

Merci quand même !
Philippe

Avatar
JustMe
Ph. Chantry wrote:

Attention c'est du QND (Quic 'n dirty) et j'ai pas faits de tests


intensifs)

JM


#include <stdio.h>

main( int argc, char **argv)



Ben c'est sympa, ça ! Je n'ai pas eu le temps de répondre "oui" que le code
est déjà pondu !

Les premiers tests ne sont hélas pas conluants:

# cat A
a
# cat B
b
b
b
# ./a.out A B
# cat B
a
b
b


#

Merci quand même !
Philippe




Bizarre chez moi ca marche avec les memes fichiers sources...


Avatar
Nicolas Le Scouarnec
cat B >> A
J'avais oublié de préciser que la taille de A est négligeable devant celle

de B, et que B est, en général, un assez gros fichier (500 Mo; je sais, avec
les disques qu'on vend aujourd'hui c'est ridicule, mais je dois vivre sur un
vieux serveur souvent à la limite de la saturation.).
Tes deux premières suggestions nécessitent un espace disponible égal à la
taille de B, ce qui ramène quasiment à mon problème initial.


Oui, en fait, il y a une fonction append dans l'accès aux fichiers,
mais elle ne que rajouter des données a la fin d'un fichier, et non pas
au début. Tu devras donc stocker une copie de tout ton fichier quelque
part pendant la réécriture (en ram par exemple).

Ou alors, tu crées un programme qui fait:
variable n=taille_du_fichier_A;
variable buffer1 (de taille n).
variable buffer2
on place les n premiers octets de B dans le buffer
on écrit les n octets de A au début de B.
on se place a la position n+1 dans B.
on lit les n octets dans buffer2.
tant_que(buffer1 n'est pas vide)
on écrit buffer1 a la position courante dans B.
on place buffer2 dans buffer1
on se place a n+1 octets en plus.
on lit n octets dans buffer2.
fin_tant_que

Peut etre en perl ?

--------------------------(A tester)-
#!/usr/bin/perl
open A, "< $ARGV[0]";
open B, "<+ $ARGV[1]";

my $tamp1;
my $tamp2;
my $n=read(A,$tamp1,1000000000000000) # On veut attendre la
# du fichier, je ne sais
# pas si 0 marche.
my $position=0

seek(B,$position,0);
read(B,$tamp2,$n);
while(length($temp1)!=0){
print B $tamp1;
$position+=$n;
seek(B,$position,0);
$tamp1=$tamp2;
read(B,$tamp2,$n);
}

close A;
close B;

-------------------------------------

La troisième solution marche avec de petits fichiers, mais plante avec un
gros B. Je n'ai pas cherché à trouver la cause de plantage. Le taille du
fichier manipulé reste en dessous des limites système données par ulimit -a.


Il essaye de lire tout le fichier dans la mémoire avant de commencer a
le donner a l'autre shell. Il ne doit pas aimer les 500 Mo...


--
Nicolas Le Scouarnec
http://nlsn.free.fr (Slrnfr, Docs Linux/BSD, La grippe, ... )


Avatar
Laurent Wacrenier
Ph. Chantry écrit:
Je voudrais ajouter des lignes au début d'un fichier.
Sauriez-vous comment faire sans passer par un fichier intermédiaire ?


Rien à part mettre les données en mémoire le temps de la copie.

Peut-être quelqu'un a-t-il déjà développé ça ?


Il faudrait patcher le système de fichiers.

Avatar
Laurent Wacrenier
Laurent Wacrenier écrit:
Peut-être quelqu'un a-t-il déjà développé ça ?


Il faudrait patcher le système de fichiers.


Quoique.

Il faudrait décaler les données du fichier destinataires d'autant
d'octets que nessessaire pour ajouter les données.

Comme ceci, par exemple (en ajoutant le contrôle des erreurs et en
priant que le programme ne s'arrete pas en route, auquel cas les
données sont perdues) :

#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char **argv) {
char *dst = argv[1]; /* fichier à éditer */
char *add = argv[2]; /* fichier à ajouter */
off_t add_len;
off_t dst_len;
void *add_data;
void *dst_data;
int add_fd = open(add, O_RDONLY);
int dst_fd = open(dst, O_RDWR);
add_len = lseek(add_fd, 0, SEEK_END);
if (add_len == 0) return 0;
dst_len = lseek(dst_fd, add_len - 1 , SEEK_END);
write(dst_fd, "", 1);
dst_len ++;

add_data = mmap(NULL, add_len, PROT_READ, MAP_PRIVATE, add_fd, 0);
dst_data = mmap(NULL, dst_len,
PROT_READ|PROT_WRITE, MAP_SHARED, dst_fd, 0);
close(add_fd);
close(dst_fd);

memmove(dst_data+add_len, dst_data, dst_len - add_len);
memmove(dst_data, add_data, add_len);
munmap(dst_data, dst_len);
munmap(add_data, add_len);
return 0;
}


Avatar
Ph. Chantry
Il faudrait décaler les données du fichier destinataires d'autant
d'octets que nessessaire pour ajouter les données.

Comme ceci, par exemple (en ajoutant le contrôle des erreurs et en
priant que le programme ne s'arrete pas en route, auquel cas les
données sont perdues) :

#include <sys/mman.h>


Merci pour ce code !
Je n'ai pas encore eu le temps de le tester.

Philippe

1 2