youtube-dl, как записать все сабвуферы плейлиста youtube в ОДИН файл?

How to delete a file at the same time that it is added in an archive?

Учитывая контекст, я интерпретирую этот вопрос как:

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

Преобразование может быть любым, что вы хотите сделать с данными :сжатием, шифрованием и т. д.

Ответ таков:

<$file gzip | dd bs=$buffer iflag=fullblock of=$file conv=notrunc

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

.
cat "$file" \
| pv -cN 'bytes read from file' \
| gzip \
| pv -cN 'bytes received from compressor' \
| dd bs=$buffer iflag=fullblock 2>/dev/null \
| pv -cN 'bytes written back to file' \
| dd of="$file" conv=notrunc 2>/dev/null

Я пройдусь по строчке за строчкой:

cat "$file"читает файл, который вы хотите сжать. Это бесполезное использование cat (UUOC ), так как следующая часть, pv, также может читать файл, но я считаю, что это красивее.

Он направляет его в pv, который показывает информацию о ходе выполнения (-cN, говорит ему «использовать какой-то [c]курсор» и дает ему [Имя] ).

Это направляет в gzip, что, очевидно, выполняет сжатие (, чтение со стандартного ввода и вывод на стандартный вывод ).

Этот канал переходит в другойpv(вид трубы ).

Этот канал в dd bs=$buffer iflag=fullblock. Переменная $buffer— это число, примерно 50 мегабайт. Независимо от того, сколько оперативной памяти вы хотите выделить для безопасной обработки вашего файла (в качестве точки данных, 50-мегабайтный буфер для 2-гигабайтного файла вполне подойдет ). iflag=fullblockуказывает ddпрочитать до $bufferбайт перед передачей по конвейеру. В начале gzip запишет заголовок, поэтому вывод gzip попадет в эту строку dd. Затем ddбудет ждать, пока у него не будет достаточно данных, прежде чем передать их по конвейеру, чтобы ввод мог читаться дальше. Кроме того, если у вас есть несжимаемые части, выходной файл может быть больше, чем входной файл. Этот буфер гарантирует, что до $bufferбайт это не проблема.

Затем мы переходим к другой строке представления канала и, наконец, к нашей выходной строке dd. В этой строке указаныof(выходной файл )и conv=notrunc, где notruncуказывает ddне усекать (удалять )выходной файл перед записью. Итак, если у вас есть 500 байтов Aи вы записываете 3 байта B, файл будетBBBAAAAA...(вместо , замененного наBBB).

Части 2>/dev/nullя не рассматривал, они не нужны. Они просто немного убирают вывод, подавляя сообщение dd«Я закончил и написал это много байтов». Обратная косая черта в конце каждой строки(\)заставляет bash рассматривать все это как одну большую команду, которая передается друг другу.


Вот полный скрипт для удобства использования. Как ни странно, я поместил его в папку под названием «gz -в -месте». Затем я понял, что аббревиатуру я сделал :GZIP :gnu zip в месте -. Итак, представляю GZIP.sh:

#!/usr/bin/env bash

### Settings

# Buffer is how many bytes to buffer before writing back to the original file.
# It is meant to prevent the gzip header from overwriting data, and in case
# there are parts that are uncompressible where the compressor might exceed
# the original filesize. In these cases, the buffer will help prevent damage.
buffer=$((1024*1024*50)) # 50 MiB

# You will need something that can work in stream mode from stdin to stdout.
compressor="gzip"

# For gzip, you might want to pass -9 for better compression. The default is
# (typically?) 6.
compressorargs=""

### End of settings

# FYI I'm aware of the UUOC but it's prettier this way

if [ $# -ne 1 ] || [ "x$1" == "x-h" ] || [ "x$1" == "x--help" ]; then
    cat << EOF
Usage: $0 filename
Where 'filename' is the file to compress in-place.

NO GUARANTEES ARE GIVEN THAT THIS WILL WORK!
Only operate on data that you have backups of.
(But you always back up important data anyway, right?)

See the source for more settings, such as buffer size (more is safer) and
compression level.

The only non-standard dependency is pv, though you could take it out
with no adverse effects, other than having no info about progress.
EOF
    exit 1;
fi;

b=$(($buffer/1024/1024));
echo "Progressing '$1' with ${b}MiB buffer...";
echo "Note: I have no means of detecting this, but if you see the 'bytes read from";
echo "file' exceed 'bytes written back to file', your file is now garbage.";
echo "";

cat "$1" \
| pv -cN 'bytes read from file' \
| $compressor $compressorargs \
| pv -cN 'bytes received from compressor' \
| dd bs=$buffer iflag=fullblock 2>/dev/null \
| pv -cN 'bytes written back to file' \
| dd of="$1" conv=notrunc 2>/dev/null

echo "Done!";

Мне хочется добавить еще одну строку буферизации перед gzip, чтобы она не записывалась слишком далеко, когда строка буферизации ddпрошивается, но с буфером всего 50 МБ и 1900 МБ данных /dev/urandomэто кажется, уже работает в любом случае (md5sums совпадают после распаковки ). Достаточно хорошее соотношение для меня.

Другим улучшением было бы обнаружение слишком далекого письма, но я не вижу, как это сделать, не лишая красоту вещи и не создавая много сложности. В этот момент вы могли бы также просто сделать его полноценной -полноценной программой на Python, которая делает все правильно (с отказоустойчивостью для предотвращения уничтожения данных ).

2
30.03.2019, 21:56
0 ответов

Теги

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