Я понял то, что я забыл, когда я спросил друга. В цикле я установил a global variable
для местоположения. В for loop
Я забыл добавлять cd $folder
перед процессом zip, который заставил это архивировать папку и содержание.
Я провел много исследований по этому вопросу. Вы можете сделать тест на файле с подсчетом слов, но он не даст вам того же числа, что и du -sb adir
.
tar -tvOf afile.tar | wc -c
du
считает каждый каталог как 4096 байт, а tar
считает каталоги как 0 байт. Вы должны добавить 4096 к каждому каталогу:
$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096)))
затем вы должны добавить все символы. Для чего-то, что выглядит так:
$(( $(tar -tvOf afile.tar 2>&1 | grep '^d' | wc -l) * 4096 + $(tar -xOf afile.tar | wc -c) ))
Я не уверен, что это идеально, поскольку я не пробовал файлы, которые были тронуты (файлы с 0 байтами) или файлы с 1 символом. Это должно приблизить вас к идеалу.
Если скорость важна, а сжатие не требуется, вы можете подключить обертки системных вызовов, используемые tar
, используя LD_PRELOAD
, чтобы изменить tar
, чтобы вычислить его для нас. Путем повторной реализации некоторых из этих функций в соответствии с нашими потребностями (расчета размера потенциальных выходных данных tar )мы можем исключить многие read
и write
, которые выполняются при нормальной работе tar
.. Это делает tar
намного быстрее, так как не нужно переключаться между контекстами в ядре почти так же часто, и нужно читать только stat
запрошенного входного файла/папки (s ). с диска вместо фактических данных файла.
Приведенный ниже код включает реализации функций close
, read
и write
POSIX. Макрос OUT_FD
определяет, какой дескриптор файла мы ожидаем, что tar
будет использоваться в качестве выходного файла. В настоящее время он установлен на стандартный вывод.
read
было изменено, чтобы просто возвращать значение успеха count
байтов вместо заполнения buf данными, учитывая, что фактические данные не были прочитаны, buf не будет содержать действительных данных для передачи в сжатие, и, таким образом, если сжатие было используется, мы рассчитали бы неправильный размер.
write
был изменен, чтобы суммировать входные count
байт в глобальную переменную total
и возвращать значение успеха count
байт только , если дескриптор файла соответствует OUT_FD
, в противном случае он вызывает исходный оболочка, полученная через dlsym
для выполнения одноименного системного вызова.
close
по-прежнему выполняет все свои исходные функции, но если дескриптор файла соответствует OUT _FD, он знает, что tar
пытается записать tar-файл, поэтому номер total
является окончательным и печатает его. в стандартный вывод.
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>
#define OUT_FD 1
uint64_t total = 0;
ssize_t (*original_write)(int, const void *, size_t) = NULL;
int (*original_close)(int) = NULL;
void print_total(void)
{
printf("%" PRIu64 "\n", total);
}
int close(int fd)
{
if(! original_close)
{
original_close = dlsym(RTLD_NEXT, "close");
}
if(fd == OUT_FD)
{
print_total();
}
return original_close(fd);
}
ssize_t read(int fd, void *buf, size_t count)
{
return count;
}
ssize_t write(int fd, const void *buf, size_t count)
{
if(!original_write)
{
original_write = dlsym(RTLD_NEXT, "write");
}
if(fd == OUT_FD)
{
total += count;
return count;
}
return original_write(fd, buf, count);
}
Сравнительный анализ, сравнивающий решение, в котором доступ для чтения к диску и все системные вызовы обычной операции tar выполняются с решением LD_PRELOAD
.
$ time tar -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/ | wc -c
332308480
real 0m0.457s
user 0m0.064s
sys 0m0.772s
tarsize$ time./tarsize.sh -c /media/storage/music/Macintosh\ Plus-\ Floral\ Shoppe\ \(2011\)\ \[Flac\]/
332308480
real 0m0.016s
user 0m0.004s
sys 0m0.008s
Приведенный выше код — базовый сценарий сборки для создания вышеуказанной общей библиотеки.и скрипт с "методом LD_PRELOAD
" с его использованием предоставлен в репозитории :https://github.com/G4Vi/tarsize
Немного информации об использовании LD _ПРЕДВАРИТЕЛЬНАЯ ЗАГРУЗКА:https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/