1

Я нашел несколько сценариев, объединяющих текстовые файлы из разных подкаталогов, но все они создавали выходные файлы, такие как «output.txt», но не сохраняли оригинальное имя файла.

Состав

Folder_A
   a.csv
   b.csv
   ...

Folder_B
   a.csv
   b.csv
   ...

Я хотел бы получить новый a.csv, объединенный из a.csv в Folder_A и a.csv в Folder_B и т.д., Записанный либо в родительский каталог, либо в новый выходной каталог.

В моем случае количество файлов в подкаталогах одинаковое. Там может быть более двух подкаталогов.

Результирующие csv-файлы должны содержать только одну строку заголовка.

Я знаю, что мне нужно пройтись по каталогам, но я не знаю, как создать список имен файлов и найти их, и как все это вложить.

Любая помощь приветствуется.

2 ответа2

2

Вы можете попробовать этот скрипт bash. Он находит файлы с именем «.csv» в первом каталоге и объединяет его с тем же именем, найденным во втором каталоге, после удаления (1d) своей первой строки (заголовок csv). Полученный файл находится в 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

Этот сценарий bash находит файлы с именем «.csv» в каталогах, заданных в качестве аргумента, и объединяет их с любым именем файла, найденным позже, после удаления (1d) их 1-й строки (заголовок csv). Полученный файл находится в каталоге 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
0

Проще, если вы делаете это более Unix-у, более гибко - требуется всего 2 команды:

  1. получить список имен файлов (= различное объединение файлов всех директорий)
  2. cat файл (ы) всех dirs в файл (ы) Output dir

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .