Concatene csv-files com o mesmo nome de subdiretórios

1

Encontrei alguns scripts concatenando arquivos de texto de subdiretórios diferentes, mas todos eles produziram arquivos de saída como "output.txt", mas não mantiveram o nome do arquivo original.

Estrutura

Folder_A
   a.csv
   b.csv
   ...

Folder_B
   a.csv
   b.csv
   ...

Eu gostaria de receber um novo a.csv, mesclado do a.csv em Folder_A e do a.csv em Folder_B e assim por diante, escrito no diretório pai ou em um novo diretório de saída.

No meu caso, o número de arquivos nos subdiretórios é semelhante. Pode haver mais de dois subdiretórios.

Os arquivos csv resultantes devem conter apenas uma linha de cabeçalho.

Eu sei que tenho que percorrer os diretórios, mas não tenho idéia de como criar uma lista de nomes de arquivos e procurá-los, e como aninhar tudo isso.

Qualquer ajuda gentilmente apreciada.

    
por Bernd V. 29.07.2015 / 18:26

2 respostas

2

Você pode tentar este script bash. Ele encontra arquivos com o nome '.csv' no primeiro diretório e concatena com o mesmo nome de arquivo encontrado no segundo diretório, após excluir (1d) sua primeira linha (cabeçalho csv). O arquivo resultante está no terceiro diretório.

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

Este script bash encontra arquivos chamados '.csv' nos diretórios dados como argumento e concatena-los com qualquer um dos mesmos nome do arquivo encontrado mais tarde, após excluir (1d) sua primeira linha (cabeçalho csv). O arquivo resultante está no diretório 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
    
por 29.07.2015 / 19:51
0

Mais fácil se você fizer mais Unix-y, mais shelly - apenas 2 comandos são necessários:

  1. obter lista dos nomes de arquivos (= Arquivos de União Distinta de todos os dirs)
  2. cat (s) arquivo (s) parcial (s) de todas as dirs para o (s) arquivo (s) inteiro (s) da pasta de saída

#### 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

    
por 29.07.2015 / 21:58