Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 14/06/2012, à 09:57

akrogames

Fusionner des fichiers de différents répertoires

Bonjour a tous,

J'ai deux répertoires contenant des fichiers du même nom et je souhaite fusionner les fichiers de ces répertoires entre-eux.

Exemple :
+ REP1
+ - log123
+ - log124
+ REP2
+ - log123
+ - log124

Comment je peux faire pour fusionner de manière optimale les fichiers ? Je suis obligé de faire un script shell listant les fichiers de chacun et ensuite de faire un "cat REP1/log123 >> REP2/log123"

Connaissez-vous d'autres solutions que je ne connais point ?

Merci d'avance de votre aide

Hors ligne

#2 Le 14/06/2012, à 16:31

dev/random

Re : Fusionner des fichiers de différents répertoires

Essaye:

ls -1 REP1 |
while read f; do
        [ -f REP2/$f ] && echo "cat REP1/$f >> REP2/$f" 
done

Ote echo "" si c'est ok..


667, the neighbour of the beast..

Hors ligne

#3 Le 14/06/2012, à 16:48

Hizoka

Re : Fusionner des fichiers de différents répertoires

shopt -s nullglob globstar
fichiers=( TONDOSSIER/**/log* )
cat "${fichiers[@]}" > big_log

echo "cat REP1/$f >> REP2/$f"

C'est quoi cette idée etrange ?
il va t'ecrire "cat REP1/$f >> REP2/$f" dans la console...

Dernière modification par Hizoka (Le 14/06/2012, à 16:51)


KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github

Hors ligne

#4 Le 14/06/2012, à 18:13

dev/random

Re : Fusionner des fichiers de différents répertoires

Pas du tout: il va écrire "Je n'ai pas lu le post jusqu'au bout" dans un terminal..
çtoi qu'est strange avec ton > big_log =)


667, the neighbour of the beast..

Hors ligne

#5 Le 15/06/2012, à 02:46

nesthib

Re : Fusionner des fichiers de différents répertoires

et toc tongue
@Hizoka : vite rentabilisé le « shopt -s nullglob globstar » ^^


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#6 Le 15/06/2012, à 09:24

akrogames

Re : Fusionner des fichiers de différents répertoires

ls -1 REP1 |
while read f; do
        [ -f REP2/$f ] && echo "cat REP1/$f >> REP2/$f" 
done

J'ai essayé de développé avec le script ci-dessus qui correspond le mieux à ce que je veux faire. Cependant il me fait un :
line 5: [: too many arguments

Etrange...

Hors ligne

#7 Le 15/06/2012, à 09:48

credenhill

Re : Fusionner des fichiers de différents répertoires

hello
enlever le -l du ls

Hors ligne

#8 Le 15/06/2012, à 12:38

dev/random

Re : Fusionner des fichiers de différents répertoires

akrogames a écrit :

line 5: [: too many arguments

Oups.. Doit y avoir des noms de fichier avec des espaces.

ls -1 REP1 |
while read f; do
        [ -f "REP2/$f" ] && cat "REP1/$f" >> "REP2/$f" 
done

667, the neighbour of the beast..

Hors ligne

#9 Le 19/06/2012, à 09:36

Postmortem

Re : Fusionner des fichiers de différents répertoires

dev/random a écrit :
akrogames a écrit :

line 5: [: too many arguments

Oups.. Doit y avoir des noms de fichier avec des espaces.

ls -1 REP1 |
while read f; do
        [ -f "REP2/$f" ] && cat "REP1/$f" >> "REP2/$f" 
done

Salut,
Il faut surtout éviter de boucler sur la sortie du ls

for fic in REP1/log*
do
[[ -f $fic ]] && [[ -f REP2/${fic##*/} ]] && cat "REP2/${fic##*/}" >> "$fic"
done

Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#10 Le 19/06/2012, à 10:48

dev/random

Re : Fusionner des fichiers de différents répertoires

Postmortem a écrit :
[[ -f $fic ]] && [[ -f REP2/${fic##*/} ]] && cat "REP2/${fic##*/}" >> "$fic"

1. Ca résoud pas le problème des noms de fichiers avec espace
2. Ca fait pas ce qui était demandé..


667, the neighbour of the beast..

Hors ligne

#11 Le 19/06/2012, à 19:20

Postmortem

Re : Fusionner des fichiers de différents répertoires

dev/random a écrit :

1. Ça résout pas le problème des noms de fichiers avec espace
2. Ça fait pas ce qui était demandé..

1. Pas de problème d'espace avec ma solution et je pense que c'est plus propre que de boucler sur un ls :

$ more REP*/log*
::::::::::::::
REP1/log 1
::::::::::::::
contenu fichier 'log 1' dans rep1
::::::::::::::
REP1/log 2
::::::::::::::
contenu fichier 'log 2' dans rep1
::::::::::::::
REP2/log 1
::::::::::::::
contenu fichier 'log 1' dans rep2
::::::::::::::
REP2/log 2
::::::::::::::
contenu fichier 'log 2' dans rep2

$ for fic in REP1/log*
> do
> [[ -f $fic ]] && [[ -f REP2/${fic##*/} ]] && cat "REP2/${fic##*/}" >> "$fic"
> done

$ more REP*/log*
::::::::::::::
REP1/log 1
::::::::::::::
contenu fichier 'log 1' dans rep1
contenu fichier 'log 1' dans rep2
::::::::::::::
REP1/log 2
::::::::::::::
contenu fichier 'log 2' dans rep1
contenu fichier 'log 2' dans rep2
::::::::::::::
REP2/log 1
::::::::::::::
contenu fichier 'log 1' dans rep2
::::::::::::::
REP2/log 2
::::::::::::::
contenu fichier 'log 2' dans rep2

Entre les double crochets, un mot reste un mot, c'est à dire qu'une variable, reste "un seul mot pour bash" même si elle se développe en plusieurs.
Et ma solution gère les noms de fichiers ayant des sauts de ligne (on est d'accord que c'est très rare !) ainsi que s'il y a des espaces à la fin ou au début du nom... Ce qui ne me semble pas être le cas de la tienne.


Edit :
Le while read... dans un pipe peut-être embêtant : voir ici
Et plein de lecture intéressante

2. J'ai en effet inverser REP1 et REP2.

Dernière modification par Postmortem (Le 19/06/2012, à 20:15)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#12 Le 19/06/2012, à 21:51

dev/random

Re : Fusionner des fichiers de différents répertoires

$ bash --version
GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu)
$ [[ -f avec espace ]] && /bin/false
bash: Erreur de syntaxe dans une expression conditionnelle
bash: Erreur de syntaxe près de « espace »

L'expression dans la boucle est plus simple avec le ls.


667, the neighbour of the beast..

Hors ligne

#13 Le 20/06/2012, à 05:05

nesthib

Re : Fusionner des fichiers de différents répertoires

Postmortem a écrit :

Le while read... dans un pipe peut-être embêtant

Ça n'est pas la faute du while read, mais celle du pipe smile

il suffit de ne pas utiliser de pipe mais une substitution de processus :

while read line
do
    …
done < <(commande telle que grep)

pas de pipe… pas de sous-shell
pas de sous-shell… ben pas de sous-shell…


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#14 Le 20/06/2012, à 06:49

Postmortem

Re : Fusionner des fichiers de différents répertoires

Quoiqu'il en soit, la solution avec ls n'est pas la meilleure ici, il y a plein d'exemples sur ce forum et ailleurs qui montrent les soucis que ça pose.
Et pourquoi utiliser une commande externe supplémentaire comme ls alors qu'il n'y en a pas besoin ici (avec pipe ou avec substitution de processus).

dev/random a écrit :
$ bash --version
GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu)
$ [[ -f avec espace ]] && /bin/false
bash: Erreur de syntaxe dans une expression conditionnelle
bash: Erreur de syntaxe près de « espace »

L'expression dans la boucle est plus simple avec le ls.

Bien sûr que ton exemple plante, entre double crochets, -f attend un seul argument... Donc faut protéger l'espace sauf si celui-ci est le résultat d'un expansion de variable. Par exemple, comme ça, ça fontione :

[[ -f "avec espace" ]] && echo "$var existe"
# Ou :
var="avec espace"
[[ -f $var ]] && echo "$var existe"

Et je vois pas où l'expression est plus simple dans la boucle avec ls ?
Enfin si sont les expansions avec # qui parraissent complexes, on peut les retirer facilement :

cd REP1
for fic in log*
do
[[ -f $fic ]] && [[ -f REP2/$fic ]] && cat "$fic" >> "REP2/$fic"
done

Dernière modification par Postmortem (Le 20/06/2012, à 07:02)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#15 Le 20/06/2012, à 15:01

dev/random

Re : Fusionner des fichiers de différents répertoires

nesthib a écrit :
Postmortem a écrit :

Le while read... dans un pipe peut-être embêtant

Ça n'est pas la faute du while read, mais celle du pipe smile

il suffit de ne pas utiliser de pipe mais une substitution de processus :

while read line
do
    …
done < <(commande telle que grep)

pas de pipe… pas de sous-shell

Ca génère quand même un pipe, on est bien d'accord.. implicite, mais bien réel:

$ while read a; do
 echo $a
done < $(cat) &
[1] 25681
$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
xxxx     20065  4925  0 Jun19 pts/3    00:00:00 bash
xxxx     25681 20065  0 13:09 pts/3    00:00:00 bash
xxxx     25682 25681  0 13:09 pts/3    00:00:00 cat
$ ll /proc/25682/fd
lrwx------ 1 xxxx xxxx 64 juin  20 13:10 0 -> /dev/pts/3
l-wx------ 1 xxxx xxxx 64 juin  20 13:10 1 -> pipe:[679526] # sortie standard de cat
$ ll /proc/25681/fd
lrwx------ 1 xxxx xxxx 64 juin  20 13:10 0 -> /dev/pts/3
lrwx------ 1 xxxx xxxx 64 juin  20 13:10 1 -> /dev/pts/3
lrwx------ 1 xxxx xxxx 64 juin  20 13:09 2 -> /dev/pts/3
lrwx------ 1 xxxx xxxx 64 juin  20 13:10 255 -> /dev/pts/3
lr-x------ 1 xxxx xxxx 64 juin  20 13:10 3 -> pipe:[679526] # pipe du (bout de) shell
nesthib a écrit :

pas de sous-shell… ben pas de sous-shell…

..et pas tout les ennuis qui vont avec..





Postmortem a écrit :
cd REP1
for fic in log*
do
[[ -f $fic ]] && [[ -f REP2/$fic ]] && cat "$fic" >> "REP2/$fic"
done

Encore raté, celui-là fait rien du tout. Tu devrais tester tes shells avant de les poster..


667, the neighbour of the beast..

Hors ligne

#16 Le 20/06/2012, à 15:08

nesthib

Re : Fusionner des fichiers de différents répertoires

@dev/random : oui, c'est ce que fait bash en interne, il utilise un FIFO. C'est précisé dans le man pour ceux que ça intéresse.

   Process Substitution
       Process  substitution  is supported on systems that support named pipes
       (FIFOs) or the /dev/fd method of naming open files.  It takes the  form
       of  <(list) or >(list).  The process list is run with its input or out‐
       put connected to a FIFO or some file in /dev/fd.  The name of this file
       is  passed  as  an argument to the current command as the result of the
       expansion.  If the >(list) form is used, writing to the file will  pro‐
       vide  input  for list.  If the <(list) form is used, the file passed as
       an argument should be read to obtain the output of list.

       When available, process substitution is performed  simultaneously  with
       parameter  and variable expansion, command substitution, and arithmetic
       expansion.

GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#17 Le 20/06/2012, à 15:36

Postmortem

Re : Fusionner des fichiers de différents répertoires

dev/random a écrit :
Postmortem a écrit :
$ cd REP1
for fic in log*
do
[[ -f $fic ]] && [[ -f REP2/$fic ]] && cat "$fic" >> "REP2/$fic"
done

Encore raté, celui-là fait rien du tout. Tu devrais tester tes shells avant de les poster..

Oui, j'ai voulu adapté un peu vite sans tester ; il faut préciser le chemin complet pour REP2 ou alors relativement à REP1 :

cd REP1
$ for fic in log*
> do
> [[ -f $fic ]] && [[ -f ../REP2/$fic ]] && cat "$fic" >> "../REP2/$fic"
> done

Néanmoins, je maintiens que la boucle for est la plus adaptée ici... Pas de sous-shell, et aucun souci peu importe le nom du fichier !

Dernière modification par Postmortem (Le 20/06/2012, à 15:36)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#18 Le 20/06/2012, à 16:18

dev/random

Re : Fusionner des fichiers de différents répertoires

FIFO ? Non.. le pipe() simple est beaucoup plus rapide. Le man dit: "named pipes (FIFOs) or the /dev/fd method":
il y a un lien /dev/fd -> /proc/self/fd, où on voit apparaitre le pipe, comme mis en #15.

Ca apparait aussi avec cette manip':

$ cat a.sh
#!/bin/bash
while read a; do
 echo $a
done < $(cat)
$ strace -f -o f bash a.sh
^D
$ egrep 'exec|fifo|pipe|dup' f
26964 execve("/bin/bash", ["bash", "a.sh"], [/* 38 vars */]) = 0
26964 pipe([3, 4])                      = 0
26965 dup2(4, 1)                        = 1
26965 execve("/bin/cat", ["cat"], [/* 37 vars */]) = 0
$

C'est du classique pipe-fork-dup-exec..


667, the neighbour of the beast..

Hors ligne