Menggabungkan file csv dengan nama yang sama dari subdirektori

1

Saya menemukan beberapa skrip yang menggabungkan file teks dari subdirektori yang berbeda, tetapi semuanya menghasilkan file output seperti "output.txt", tetapi tidak menyimpan nama file aslinya.

Struktur

Folder_A
   a.csv
   b.csv
   ...

Folder_B
   a.csv
   b.csv
   ...

Saya ingin menerima a.csv baru, digabung dari a.csv di Folder_A dan a.csv di Folder_B dan seterusnya, ditulis baik ke direktori induk atau direktori keluaran baru.

Dalam kasus saya, jumlah file dalam subdirektori sama. Mungkin ada lebih dari dua subdirektori.

File csv yang dihasilkan hanya boleh berisi satu baris header.

Saya tahu bahwa saya harus mengulang direktori, tetapi saya tidak tahu bagaimana cara membuat daftar nama file dan mencari mereka, dan bagaimana membuat sarang semua ini.

Setiap bantuan mohon dihargai.

Bernd V.
sumber

Jawaban:

3

Anda dapat mencoba skrip bash ini. Ia menemukan file bernama '.csv' di direktori pertama dan menggabungkannya dengan nama file yang sama yang ditemukan di direktori ke-2, setelah menghapus (1d) baris pertama (header csv). File yang dihasilkan ada di direktori ke-3.

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

Script bash ini menemukan file bernama '.csv' di direktori yang diberikan sebagai argumen dan menyatukannya dengan nama file yang sama yang ditemukan kemudian, setelah menghapus (1d) baris pertama mereka (csv header). File yang dihasilkan ada di direktori 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
meuh
sumber
Terima kasih banyak. Yang ini berhasil untuk saya. Btw, apakah ada cara untuk menghindari pengodean nama folder? Mungkin juga ada 10 atau 50 atau 100 subfolder ... (untungnya tidak sekarang)
Bernd V.
@BerndV. Apakah Anda ingin menemukan semua file yang disebut a.csv di mana pun mereka berada dan menggabungkannya menjadi satu file dengan nama yang sama, dan juga untuk semua nama file * .csv?
meuh
Ya saya ingin menemukan semua a.csv di subfolder dari direktori saat ini dan menyatukannya dengan a.csv baru di direktori saat ini (atau dalam "output" -folder ") dan seterusnya untuk csv lainnya. Csv ini adalah tabel yang diekspor dari Access mdb dengan tata letak tabel yang sama persis, yang harus saya gabungkan untuk diproses lebih lanjut. (Tidak perlu mdb baru, saya cukup senang dengan csv ketika saya membacanya di R)
Bernd V.
Ahh, baru saja melihat jawaban Anda yang diperbarui. fi >> "$ dest / base" tidak memiliki $ at base, tapi sekarang ia berjalan dengan lancar dan semuanya terlihat sempurna!
Bernd V.
0

Lebih mudah jika Anda melakukannya lebih Unix-y, lebih shelly - hanya 2 perintah yang diperlukan:

  1. dapatkan daftar nama file (= Serikat yang berbeda dari semua file direktori)
  2. cat semua dirs 'file-file ke seluruh file-dir dir ini

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

Darcy
sumber
Maaf, saya menyesatkan Anda dengan nama folder. Folder_A, Folder_B hanya untuk menunjukkan struktur. Mereka memiliki nama lain sepenuhnya tanpa pola apa pun. Mencoba mengubah itu dalam skrip gagal. Sama seperti pada jawaban lainnya: Apakah ada cara untuk menghindari pengkodean nama subfolder dengan susah payah?
Bernd V.