эффективное объединение 5 миллионов файлов

Оригинал:

<нужны файлы или дескрипторы файлов, в то время как у вас есть подстановка команды -, которая заменяет любые обратные кавычки строкой текста.

Для ваших целей лучше использовать подстановку процесса в bash. Примерно так:

gmx --stdin < <(node e "console.log('foo')")

Или другой пример для ясности:

wc -l < <(df)

Редактировать:

Чтобы передать строковый литерал, представляющий команду, вы можете использовать:

gmx --stdin <<< "$(echo node -e $'"console.log(\'foo\')"' )"

$'...'позволяет цитировать C -, что и делает часть \'foo\'.

Здесь в основном тот же пример, но вместо него используется канал (, который может не работать, если для команды требуется lseekable ввод)

$ touch with\ space
$ echo stat $'\'with space\''
stat 'with space'
$ echo stat $'\'with space\'' | sh
  File: with space
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 801h/2049d  Inode: 1069455     Links: 2
Access: (0755/drwxr-xr-x)  Uid: ( 1000/     xie)   Gid: ( 1000/     xie)
Access: 2018-05-07 05:01:37.638553045 +0800
Modify: 2018-05-07 05:01:37.638553045 +0800
Change: 2018-05-07 05:01:37.638553045 +0800
 Birth: -

Кроме того, существует способ работы с цитированием через printf %q, который из help printfописывается как:

quote the argument in a way that can be reused as shell input

Таким образом, потенциальное решение

printf '%q'  'node -e "conlose.log('foo')"' | gmx --stdin

или

gmx --stdin <<< "$( printf '%q'  'node -e "conlose.log('foo')"' )"

3
18.09.2020, 23:19
2 ответа

Если требуется удаление файлов по ходу дела, то то, что вы написали, уже является быстрым способом сделать это. Одна оптимизация заключается в том, что вместо использования findдля вывода списка содержимого файла вы можете использовать *, в котором перечислены файлы в том виде, в котором они перечислены в списке каталога, без дополнительного времени обработки из find. А именно, вы бы написали:

for i in *; do tail -n +3 $i >>../x; rm $i; done

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

find. -exec tail -n +3 {} >>../x +

+в конце указывает findпередавать имена файлов по нескольку раз, а не по одному. Это приведет к огромному увеличению производительности (из-за гораздо меньшего количества экземпляров tail, называемых ), но в вашем выходном файле все равно будет что-то вроде

==>./filename <==

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

Если вы хотите удалить строку выше за счет небольшого снижения скорости, вы можете запустить ее через

find. -exec awk 'FNR>32' {} + 

(спасибо dave _thompson за предложение в качестве комментария ).

Наконец, если вы предпочитаете вывод, в котором перечисляется, какая информация получена из какого файла, и вы все равно хотели бы удалять их по мере продвижения,вы можете использовать ответ iruvar, чтобы сделать это, с заменой обоих \;на +(мой первоначальный ответ только описывал, что делать; iruvar дал фактическую команду для этого ).

2
18.03.2021, 23:04

Скорее всего, ваш процесс связан с вводом-выводом -, поэтому оптимизация цикла даст в лучшем случае незначительные улучшения. Если вы согласны работать с глубиной файлов -, вы можете перенести вызовы tailи rmв find, удаляя по мере продвижения

С GNUfind:

find. -type f -exec tail -n +32 {} \; -delete >../all.txt

В идеале мы хотели бы получить findдля одновременной передачи нескольких файлов в tail, заменив \;на +, но я не могу заставить это работать в сочетании с-delete

С find, в котором отсутствует опция -delete

find. -type f -exec tail -n +32 {} \; -exec rm {} \; >../all.txt

или в системе GNU, которая позволяет передавать -qв tailдля подавления печати заголовков файлов, когда tailполучает несколько файлов:

find. -type f -exec tail -q -n +32 {} + -exec rm {} + >../all.txt    

Примечание -с -exec rm,глубина -первого поиска, применимая к -delete, больше не применяется Это последнее заклинание, вероятно, окажется самым действенным из всех

.
1
18.03.2021, 23:04

Теги

Похожие вопросы