У меня есть ± 10000 файлов ( res.1
- res.10000
), все состоящие из одного столбца и равного количества строк. То, что я хочу, по сути, просто; объединить все файлы по столбцам в новый файл final.res
. Я пытался с помощью:
paste res.*
Однако (хотя это , кажется, работает для небольшого подмножества результирующих файлов, это дает следующее сообщение об ошибке , когда выполняется на всем множестве: Too many open files
.
Должен быть «простой» способ сделать это, но, к сожалению, я совсем новичок в Unix. Заранее спасибо!
PS: Чтобы дать вам представление о том, как (один из моих) файлов данных выглядит:
0.5
0.5
0.03825
0.5
10211.0457
10227.8469
-5102.5228
0.0742
3.0944
...
command-line
text-processing
columns
paste
коврики
источник
источник
--serial
опцию сpaste
командой?paste --serial
не объединяет файлы по столбцам ...paste -s
действительно работает, но вставляет отдельные файлы результатов по строкам, а не по столбцам. Тем не менее, это то, что я могу решить. Благодарность!Ответы:
Если у вас есть права root на этом компьютере, вы можете временно увеличить ограничение «максимальное количество дескрипторов открытых файлов»:
А потом
После этого вы можете вернуть его к исходным значениям.
Второе решение , если вы не можете изменить ограничение:
Он вызывает
paste
каждый файл один раз, и в конце появляется огромный файл со всеми столбцами (это занимает минуту).Редактировать : Бесполезное использование кошки ... Не !
Как уже упоминалось в комментариях, использование
cat
здесь (cat final.res | paste - $f >temp
) не бесполезно. При первом запуске цикла файлfinal.res
еще не существует.paste
затем потерпит неудачу, и файл никогда не будет ни заполнен, ни создан. С моим решениемcat
не удается только в первый разNo such file or directory
иpaste
читает из стандартного ввода только пустой файл, но это продолжается. Ошибка может быть проигнорирована.источник
ulimit -Sn
для мягкого ограничения иulimit -Hn
для жесткого ограничения-bash: /usr/bin/paste: Argument list too long
. Идеи как это решить? Извините, что беспокою вас, ребята.getconf ARG_MAX
, вы можете только увеличить это значение при перекомпиляции ядра. Вы можете попробовать мое второе решение?cat
каждый раз в цикле, вы можете начать с создания пустогоfinal.res
файла. В любом случае, это хорошая идея, если там уже естьfinal.res
файл.Если ответ хаоса неприменим (поскольку у вас нет необходимых разрешений), вы можете разделить
paste
вызовы следующим образом:Этот список файлов 1000 в то время , в файлы с именами
lists00
, иlists01
т.д., а затем вставляет соответствующиеres.
файлы в файлы с именамиmerge00
, иmerge01
т.д., и , наконец , объединяет все полученные частично объединены файлы.Как уже упоминалось, хаос вы можете увеличить количество файлов, используемых одновременно; предел - это заданное значение
ulimit -n
минус сколько файлов у вас уже открыто, так что вы бы сказалииспользовать лимит минус десять.
Если ваша версия
split
не поддерживает-d
, вы можете удалить ее: все, что она делает, это говоритsplit
использовать числовые суффиксы. По умолчанию суффиксы будетaa
, иab
т.д. , а не01
, и02
т.д.Если существует так много файлов, которые
ls -1 res.*
терпят неудачу («список аргументов слишком длинный»), вы можете заменить его,find
чтобы избежать этой ошибки:(Как указывает don_crissti , он
-1
не должен быть необходим приls
выводе данных по конвейеру ; но я оставляю его для обработки случаев, когдаls
используется псевдоним-C
.)источник
Попробуйте выполнить это следующим образом:
Вы также можете разбить партию на части и попробовать что-то вроде:
и в конце объединить окончательные файлы
источник
Too many open files
final.x00
be-каналов - как именованных FIFO, так и неявно, используя подстановку процессов (если ваша оболочка это поддерживает - например, bash). Это не весело писать вручную, но вполне может подойти для make-файла.Я не думаю, что это так сложно, как все - вы уже проделали тяжелую работу, заказав имена файлов. Только не открывайте их все одновременно, вот и все.
Другой путь:
... но я думаю, что это делает их в обратном направлении ... Это может работать лучше:
И вот еще один способ:
Это позволяет
tar
собрать все файлы в поток с нулевым разделением для вас, проанализировать все метаданные заголовка, кроме имени файла, и преобразовать все строки во всех файлах во вкладки. Тем не менее, он полагается на то, что входные данные являются фактическими текстовыми файлами, то есть каждый из них заканчивается символом новой строки и в файлах нет нулевых байтов. Да, и это также зависит от того, что сами имена файлов не имеют перевода строки (хотя это может быть надежно обработаноtar
с помощью--xform
опции GNU ) . Учитывая эти условия, он должен очень быстро работать с любым количеством файлов - иtar
сделает почти все.Результатом является набор строк, которые выглядят так:
И так далее.
Я проверил это, сначала создав 5 тестовых файлов. На самом деле я не чувствовал, что сейчас создаю 10000 файлов, поэтому я стал немного больше для каждого - и также убедился, что длины файлов сильно различаются. Это важно при тестировании
tar
сценариев, посколькуtar
блокирует ввод данных фиксированной длины - если вы не попробуете хотя бы несколько разных длин, вы никогда не узнаете, будете ли вы обрабатывать только одну из них.Во всяком случае, для тестовых файлов я сделал:
ls
впоследствии сообщили:... тогда я побежал ...
... просто чтобы показать только первые 25 полей с разделителями табуляции в строке (потому что каждый файл - это одна строка - их много ) ...
Выход был:
источник
Учитывая количество файлов, размеры строк и т. Д., Я думаю, что оно превзойдет размеры инструментов по умолчанию (awk, sed, paste, * и т. Д.)
Я бы создал для этого небольшую программу, в которой не было бы ни 10 000 открытых файлов, ни строки длиной в сотни тысяч (10 000 файлов из 10 (максимальный размер строки в примере)). Для хранения количества байтов, считанных из каждого файла, требуется всего ~ 10000 целых чисел. Недостатком является то, что он имеет только один дескриптор файла, он используется повторно для каждого файла, для каждой строки, и это может быть медленным.
Определения
FILES
иROWS
должны быть изменены на фактические точные значения. Вывод отправляется на стандартный вывод.источник