1 votes

Concaténation de fichiers csv de même nom provenant de sous-répertoires

J'ai trouvé quelques scripts concaténant des fichiers texte de différents sous-répertoires, mais tous produisaient des fichiers de sortie comme "output.txt", mais ne gardaient pas le nom du fichier original.

Structure

Folder_A
   a.csv
   b.csv
   ...

Folder_B
   a.csv
   b.csv
   ...

Je voudrais recevoir un nouveau a.csv, fusionné à partir du a.csv du dossier_A et du a.csv du dossier_B et ainsi de suite, écrit soit dans le répertoire parent soit dans un nouveau répertoire de sortie.

Dans mon cas, le nombre de fichiers dans les sous-répertoires est similaire. Il pourrait y avoir plus de deux sous-répertoires.

Les fichiers csv résultants ne doivent contenir qu'une seule ligne d'en-tête.

Je sais que je dois parcourir les répertoires en boucle, mais je n'ai aucune idée de la façon dont je peux créer une liste de noms de fichiers et les rechercher, et comment imbriquer tout cela.

Toute aide est la bienvenue.

3voto

meuh Points 5650

Vous pouvez essayer ce bash script. Il trouve les fichiers nommés '.csv' dans le premier répertoire et les concatène avec le même nom de fichier trouvé dans le 2ème répertoire, après avoir supprimé (1d) sa 1ère ligne (en-tête csv). Le fichier résultant se trouve dans le 3ème répertoire.

a=Folder_A
b=Folder_B
c=Folder_C
mkdir -p $c
(cd $a && find . -type f -name '*.csv') |
while read file
do    ( cat "$a/$file"
        [ -f "$b/$file" ] && sed '1d' <"$b/$file"
      ) >"$c/$file"
done

Ce script bash script trouve des fichiers nommés '.csv' dans les répertoires donnés en argument. comme argument et les concatène avec ceux du même nom de fichier trouvés plus tard, après avoir supprimé (1d) leur 1ère ligne (en-tête csv). Le fichier résultant se trouve dans le répertoire Folder_concat.

#!/bin/bash
dest=Folder_concat
mkdir -p $dest
find "$@" -name "$dest" -prune -o -name '*.csv' |
while read file
do    base=$(basename "$file")
      if [ -s "$dest/$base" ]
      then sed '1d' <"$file"
      else cat "$file"
      fi >>"$dest/$base"
done

0voto

Darcy Points 1

C'est plus facile si vous le faites à la manière d'Unix, plus discret - seulement 2 commandes nécessaires :

  1. obtenir la liste des noms de fichiers (=Union distincte de tous les fichiers des répertoires)
  2. cat all dirs' part-file(s) into Output dirs' whole-file(s)

#### get list of files as Distinct Union of all dirs' files # (alas, basename can only handle ONE filename at a time # so have to loop through them)

DISTINCTUNION_ALLFILES=`
  for FILE in Folder_{A,B,C,D}/*
  do
    basename $FILE
  done  | sort  | uniq

  `
# 
# syntax explanation:
#  1. for VARIABLE in LIST: loops b/w DO and DONE, with Variable taking each value in the list
#  2. {A,B,C} is Shell (bash) expansion: creates N words, 1 for each comma-separated sub-word
#           e.g.: dir{A,B}            -> dirA  dirB     
#           e.g.: myfile.{dll,o,out}  -> myfile.dll  myfile.o  myfile.out
#           e.g.: myfile{,.tmp}       -> myfile  myfile.tmp
#  3. BASENAME strips away the Path leaving just the filename (cf.Dirname for the opposite)
#  4. the BACKQUOTES (``) take the command's Output and re-place it on that part of the commandline
#  5. | takes the total output and Sorts it, then | takes _that_ to Uniq which removes duplicates
#  6. the whole lot is then stored in the VariableName

#### cat all dirs' part-file(s) into Output dir's whole-file(s)

for FILE in $DISTINCTUNION_ALLFILES
do
    cat Folder_{A,B,C,D}/$FILE  > OutputDir/$FILE
done
#
# syntax explanation:
# 1. same For loop as before, same filename expansion as before
# 2. files which are not in ALL dirs will generate errors but won't stop the conCATenation
# 3. result goes into OutputDir, 1 file per filename

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X