Разделение нескольких входных файлов на несколько выходных данных с использованием функции разделения в Linux

#bash #loops #for-loop #split #vcf-variant-call-format

#bash #циклы #цикл for #разделение #vcf-variant-call-format

Вопрос:

У меня есть 8 файлов, которые я хотел бы разделить на 5 блоков для каждого файла. Обычно я бы делал это по отдельности, но хотел бы запустить это как цикл. Я работаю в HPC.

Я создал список имен файлов и пометил его «variantlist.txt «. Мой код:

 for f in 'cat variantlist.txt'; do split ${f} -n 5 -d; done 
  

Однако это разбивает только конечный файл в variantlist.txt файл, выводящий 5 фрагментов только из окончательной записи.

Даже если я перечисляю файлы по отдельности:

 for f in chr001.vcf chr002 ...chr008.vcf ; do split ${f} -n 5 -d; done
  

Он по-прежнему разбивает конечный файл только на 5 фрагментов.

Не уверен, где я здесь ошибаюсь. Желаемый результат должен составлять 40 фрагментов, по 5 на хромосому. Мы были бы очень признательны за вашу помощь.

Большое спасибо

Комментарии:

1. Не используйте for f in 'cat variantlist.txt'; . Для получения того же результата попробуйте lst=( $(<variantlist.txt) ); for f in "${lst[@]}" или while read f;do ... done<variantlist.txt или даже xargs ... < variantlist.txt .

2. @PaulHodges спасибо! Метод cat не так эффективен?

3. Посмотрите на бесполезное использование cat наград 😉

Ответ №1:

Разделение заключается в создании каждый раз одного и того же набора файлов и перезаписи предыдущих. Вот один из способов справиться с этим —

 for f in $(<variantlist.txt)  # don't use cat
do  mkdir -p $f.split         # make a subdir for the files
    ( cd $f.split amp;amp;          # change into the subdir only in a subshell
      split ../$f -n 5 -d     # split from there
    )                         # close the subshell, parent still in base dir
done
  

Или вы могли бы просто сделать это —

 while read f             # grab each filename
do split $f -n 5 -d      # split it
   for x in x??          # for each split file
   do mv $x $f.$x        # rename it to include the parent file name
   done
done < variantlist.txt   # take names from this file
  

Это намного медленнее, но не использует вложенные файлы.

Мой любимый, хотя —

 xargs -I {} split {} -n 5 -d {} < variantlist.txt
  

Последний аргумент становится ПРЕФИКСОМ для split вместо значения по умолчанию x .

РЕДАКТИРОВАТЬ — с 2 миллиардами строк в файле используйте эту:

 for f in $(<variantlist.txt)
do split "$f" -d -n 5 "$f" amp; # run all in background at the same time
done
  

Комментарии:

1. У вас достаточно места? Требуется сжатие?

2. Я запускаю его в интерактивном режиме на HPC, поэтому обновлю вас, как только это будет сделано. Ошибок пока нет, и он работает дольше, чем раньше, что является хорошим знаком (используя ваш отредактированный метод).

3. все еще выполняется! Не уверен, сколько времени это займет

4. два миллиарда строк займут некоторое время …. вы сначала пробовали это на небольших наборах данных?

5. да, я работал с меньшим набором данных. Еще раз большое спасибо за вашу помощь!

Ответ №2:

При использовании split -n swicth определяет количество выходных файлов, на которые разбивается исходный файл…

Вам нужно -l столько строк, сколько вам нужно, в вашем случае 5:

  split -l 5 ${f}
  

Комментарии:

1. спасибо за ответ. Файл на самом деле содержит 2 миллиарда строк, и я хочу, чтобы из этого было 5 файлов, то есть примерно 400 миллионов строк на файл. Если я напишу: split -l 400000000 $ {f} в цикле, это будет лучше?

2. Да, числа, переданные в -l , дадут вам слишком много строк на файл.