#performance #bash #fifo
#Производительность #bash #fifo
Вопрос:
У меня есть несколько отсортированных файлов в папке gzipped. Как мне объединить некоторые из них в другой отсортированный архивированный файл? Прямо сейчас я использую явный fifos. Есть ли способ сделать это в bash без? Я немного новичок в bash, поэтому, пожалуйста, извините за отсутствие стиля.
#!/bin/bash
# Invocation ./merge [files ... ]
# Turns an arbitrary set of sorted, gzipped files into a single sorted, gzipped file,
# printed to stdout. Redirect this script's output!
for f in $@
do
mkfifo $f.raw
gzcat $f > $f.raw amp;
# sort -C $f.raw
done
sort -mu *.raw | gzip -c # prints to stdout.
rm -f *.raw
Я хочу преобразовать это во что-то вроде…
sort -mu <(gzcat $1) <(gzcat $2) <(gzcat $3) ... | gzip -9c # prints to stdout.
…но не знаю как. Нужен ли мне цикл, преобразующий параметры в строку? Есть ли какой-нибудь волшебный ярлык для этого? Возможно map gzcat $@
?
ПРИМЕЧАНИЕ: Объем каждого из файлов превышает 10 ГБ (и 100 ГБ распакованы). У меня накопитель объемом 2 ТБ, так что на самом деле это не проблема. Кроме того, эта программа ДОЛЖНА выполняться в O (n), иначе это становится невозможным.
Комментарии:
1. Я вижу, вы отредактировали вопрос, пока я отвечал — да, вам нужен цикл для построения командной строки и либо
eval
, либоbash -c "$cmd"
для ее выполнения в конце.
Ответ №1:
Вы можете объединить eval
и «подстановку процесса» с помощью Bash. Предполагая, что основные имена файлов не содержат пробелов (что, учитывая, что вы используете $@
вместо "$@"
, вероятно, имеет место), тогда что-то вроде:
cmd="sort -mu"
for file in "$@"
do cmd="$cmd <(gzip -cd $file)"
done
eval $cmd | gzip -c9 > outputfile.gz
Вы также можете использовать bash -c "$cmd"
вместо eval $cmd
в последней строке. Если в именах файлов есть пробелы, вам придется поработать немного усерднее. Это работает, если имена не содержат одинарных кавычек:
cmd="sort -mu"
for file in "$@"
do cmd="$cmd <(gzip -cd '$file')"
done
eval $cmd | gzip -c9 > outputfile.gz
С одинарными кавычками в именах файлов также приходится работать намного усерднее.
Ответ №2:
Для меня ваш вопрос немного неясен, но если я понимаю ваши потребности, попробуйте это:
gunzip -c file1 file2 .... | sort | gzip -9 > mergedFile.gz
Если вы хотите поместить все файлы определенного типа в 1 каталог, то вы можете использовать file*.type
в качестве входного списка для gunzip, в противном случае, согласно моему примеру, вам нужно будет явно перечислить каждый файл.
-c
Опция указывает «отправить выходные данные в стандартный вывод», который является прочитанным каналом, отправленным в sort
, который отправляет свои выходные данные в стандартный вывод, канал и в gzip, при этом его стандартный вывод перенаправляется в конечный файл. -9
Выполняется максимальное сжатие, при котором получается файл наименьшего размера (для gzip), но занимает больше времени. Вы можете указать явное число от -1 до -9, чтобы настроить размер сжатия / время сжатия в соответствии с вашими потребностями.
Я надеюсь, что это поможет.
Комментарии:
1. Я действительно хочу использовать sort -mu, который не будет работать, если мы запустим архив за один раз. Это превращает сортировку из O (nlogn) в O (n).
2. Обычно я бы использовал явное
gzip -c -9
, но, думаю, это сработает.3. Итак, у вас есть большие файлы, и вы ищете способ распараллелить процесс, предварительно отсортировав файлы меньшего размера, а затем объединив их в конце? И у вас есть несколько процессоров, которые вы можете назначить каждому процессу сортировки меньшего размера? Вы хотите сэкономить время, процессор или??? Здесь, на S.O., есть значительное количество людей, заинтересованных в настройке производительности. Вы можете добавить тег для сравнительного анализа, тестирования, настройки производительности, чтобы получить лучший совет о том, как подойти к этому. Удачи.
4. @shellter: Готово. Спасибо. Но я больше искал надежный способ создания fifos (который нельзя сломать нажатием [file].raw), чем для настройки производительности. Может быть, что-то вроде замены команд? linuxjournal.com/article/2156?page=0,1
5. Хорошо, это интересный вопрос, но я хотел бы, чтобы это было в вашем первоначальном вопросе. Мне никогда не приходилось сталкиваться с этим, поэтому у меня нет хорошего ответа. Я полагаю, недостаточно установить 600 разрешений для fifo? Как произойдет «касание» файла? Можете ли вы сделать свое имя fifo более уникальным, добавив к нему ProcessId ($ $)? Что случилось с вашим беспокойством по поводу O (nlogn) против O (n)? Спокойной ночи.
Ответ №3:
С одинарными кавычками в именах файлов также приходится работать намного усерднее.
Вот способ избежать одинарных кавычек в именах файлов (или путях к файлам), которые будут eval
‘редактироваться в переменных, заключенных в одинарные кавычки.
(
esc="'''"
file="/Applications/iWork '09/Pages.app"
file="${file//'/${esc}}"
#echo "'${file}'"; ls -bdl "'${file}'"
evalstr="echo '${file}'; ls -bdl '${file}'"
#set -xv
eval "${evalstr}"
)