Я никогда не пробовал использовать эти специфические технологии RAID, но, по моему опыту, лучше всего работать на уровне файловой системы при попытке переноса данных с одной физической реализации RAID на другую. Что я имею в виду под этим?
Я имею в виду, что я бы получил другой набор дисков и переместил содержимое с 1-го RAID-массива на промежуточное место (некоторый набор жестких дисков, необходимых для его хранения), а затем переконфигурировал бы RAID-накопители в новых технологиях RAID.
Это, безусловно, больше работы, и требует, чтобы у вас было достаточно жестких дисков, чтобы удерживать данные во время их передачи, но это проверенный и верный подход, который всегда работал для многих.
Использование некоторого пути миграции, несомненно, является менее распространенным подходом, и вы рискуете потерять свои данные в процессе их передачи. Если преобразование провалится каким-либо образом, вы все равно вернетесь к подходу, который я предлагаю.
Итак, я бы откусил пулю и пошёл с этим подходом с самого начала, он просто сработает, и вы потратите гораздо меньше своего драгоценного времени в процессе.
Другой подход к объяснению: Когда используется *
, оболочка знает, что представляют собой отдельные элементы. Вывод find
является только длинным рядом. Оболочка не знает, что такое элементы (и их сепараторы).
Подстановка команд может использоваться в специальном пути с программой, которая выдает выходные данные в кавычках; тогда проблема не появится. Но для того, чтобы сделать оболочку распознавать цитаты вам нужно, например, eval
, что часто усложняет все выражение:
eval for var in $(ls --quoting-style=shell)\; do echo '"$var"'\; done
-121--96869- Мой отклик на мгновение вызова был бы неловким
, но если вы обрабатываете много строк - и я говорю о миллионах - вы, вероятно, увидите реальную выгоду от перехода на «реальный» язык программирования.
С учетом этого (и awk
, уже взятый в качестве ответа) я написал несколько реализаций на разных языках и провел их тестирование на одном и том же наборе данных 10, 000 строк на твердотельном накопителе PCI-E.
me* (C) 0m1.734s
me (C++) 0m1.991s
me (Python/Pypy) 0m2.390s
me (perl) 0m3.024s
Thor+Glenn (sed|sh) 0m3.353s
me (python) 0m3.359s
jasonwryan+Thor (awk) 0m3.779s
rush (while read) 0m6.011s
Thor (sed) 1m30.947s
me (parallel) 4m9.429s
На первый взгляд Си выглядит лучше, но это была свинья, чтобы бежать так быстро. Pypy и C++ гораздо проще писать и выполнять достаточно хорошо , если вы не говорите о многих миллиардах строк. Если бы это было так, модернизация, чтобы сделать это все в оперативной памяти или на твердотельном накопителе, могло бы быть лучшим вложением, чем улучшение кода.
Очевидно, что за то время, которое я провел, вы, вероятно, могли бы обработать несколько сотен миллионов записей в самый медленный вариант . Если вы можете написать только awk
или Bash loops, сделайте это и продолжайте жизнь. Сегодня у меня было слишком много свободного времени.
Я также протестировал некоторые многопоточные опции (в C++ и Python и гибриды с GNU parallel
), но накладные расходы потоков полностью перевешивают любые преимущества для такой простой операции (последовательность расщепление, запись).
awk
( gawk
здесь) будет, честно говоря, моим первым портом вызова для тестирования данных, как это, но вы можете сделать довольно похожие вещи в Perl. Подобный синтаксис, но с немного лучшим дескриптором записи.
perl -ane 'open(my $fh, ">", $F[0].".seq"); print $fh $F[1]; close $fh;' infile
I , как Python. Это мой дневной язык работы, и это просто хороший, прочный и невероятно читаемый язык. Даже новичок мог догадаться, что здесь происходит.
with open("infile", "r") as f:
for line in f:
id, chunk = line.split()
with open(id + ".seq", "w") as fw:
fw.write(chunk)
Вы должны помнить, что двоичный файл python
вашего дистрибутива не является единственной реализацией Python. Когда я проводил этот же тест через Pypy, он был быстрее, чем C без дальнейшей оптимизации логики. Помните об этом, прежде чем писать Python как «медленный язык».
Я начал этот пример, чтобы увидеть, что мы действительно можем заставить мой процессор сделать, но, честно говоря, C - это кошмар для кода, если вы не трогали его в течение долгого времени. Это имеет дополнительную обратную сторону, ограничиваясь 100-char линий, хотя это очень просто, чтобы расширить это, я просто не нуждался в этом.
Моя первоначальная версия была медленнее, чем C++ и pypy, но после блога об этом я получил некоторую помощь от Джулиана Клоде .Эта версия сейчас самая быстрая из-за измененных буферов ввода-вывода. Это также много дольше и более вовлечено, чем что-либо другое.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFLEN (8 * 1024)
int main(void) {
FILE *fp;
FILE *fpout;
char line[100];
char *id;
char *token;
char *buf = malloc(BUFLEN);
fp = fopen("infile", "r");
setvbuf ( fp , buf , _IOLBF, BUFLEN );
while (fgets(line, 100, fp) != NULL) {
id = strtok(line, "\t");
token = strtok(NULL, "\t");
char *fnout = malloc(strlen(id)+5);
fnout = strcat(fnout, id);
fnout = strcat(fnout, ".seq");
fpout = fopen(fnout, "w");
setvbuf ( fpout , NULL , _IONBF , 0 );
fprintf(fpout, "%s", token);
fclose(fpout);
}
fclose(fp);
return 0;
}
Хорошо работает и намного легче писать, чем реально C. У вас есть все виды вещей, которые держат вашу руку (особенно когда речь идет о последовательностях и вводе). Все это означает, что вы можете упростить логику. strtok
в C является hog, потому что он обрабатывает весь ряд, и тогда нам нужно сделать все, что утомительное выделение памяти. Это просто летит вдоль линии, пока он не попадет на вкладку, и мы вытягиваем сегменты, как мы нуждаемся в них.
#include <fstream>
#include <string>
using namespace std;
int main(void) {
ifstream in("infile");
ofstream out;
string line;
while(getline(in, line)) {
string::size_type tab = line.find('\t', 0);
string filename = line.substr(0, tab) + ".seq";
out.open(filename.c_str());
out << line.substr(tab + 1);
out.close();
}
in.close();
}
(не версия morutils). Это хороший лаконичный синтаксис, но OMGSLOW. Возможно, я использую это неправильно.
parallel --colsep '\t' echo {2} \> {1}.seq <infile
Вот мой генератор данных для 100000 строк [ATGC] * 64. Это не быстро и улучшения очень приветствуются.
cat /dev/urandom | tr -dc 'ATGC' | fold -w 64 | awk 'NR>100000{exit}{printf NR"\t"$0"\n"}' > infile
-121--29618- Супер + пространство, затем Система, а затем Настройки дисплея для получения дополнительной информации см. http://crunchbang.org/forums/viewtopic.php?id=19797