Их около 130 миллионов (129923145, точнее, на find. -Name "*. *" | Wc -l
) картинки на сервере. Их необходимо исключить из дубликатов и упаковать в zip-архивы от самых маленьких до самых больших на каждый миллион для дальнейшего использования. (скажем, если это 500 000 уникальных изображений 8 КБ, 600 000 уникальных изображений 16 КБ, 950 000 уникальных изображений 24 КБ, я должен упаковать 500 000 изображений 8 КБ и 500 000 изображений 16 КБ в первый файл zip, затем упаковать 100 000 изображений 16 КБ и 900 000 изображений 24 КБ во второй файл. , и остальное к третьему), имя файла должно быть сохранено, и лучше сохранить информацию об иерархии.
Сервер оснащен 32 ГБ памяти, 5,5 ТБ на жестком диске (доступно 122 ГБ), ЦП выглядит как E5-2680v4 , Я не знаю, физическая это или виртуальная машина. Я мог бы попросить товарищей по ИТ добавить память до 512 ГБ, но потребуется как минимум одна неделя, чтобы получить одобрение нашего технического директора, специалистов по цепочке поставок, бюджетного комитета и ИТ-отдела, возможно, потребуется дополнительное время, чтобы убедить их.
Нет лишнего дискового пространства, которое можно было бы использовать из-за рейда или чего-то подобного (айтишниками). Это интрасеть без интернета, и я предпочитаю не отправлять файл, чем подавать приложение. Это Ubuntu 16.04, я уверен, что можно использовать vim, python (2 и 3) и оболочку. Я могу использовать только ssh и не могу sudo
.
Мое решение - использовать du -a
для создания списка файлов, используя md5sum
для de -дупликация, переименование всех файлов с абсолютным путем (замените /
на __ DIVIDER __
) и переместите весь файл в SIZE / MD5 / (fileNameWithAbsPath)
, чем выберите один для каждого каталога. Во время этого я встретил "Ошибка индекса H-дерева" . Есть ли способ лучше (быстрее, проще и т. Д.) Закончить это и, если возможно, избежать ошибки индекса H-дерева?
Кстати, я шестой по долгу службы. Первые пятеро уволились с работы: (
Таким образом, один из способов обойти ошибку, с которой вы столкнулись - это разделить размер и md5 на несколько подполей. Для размера сначала нужно разбить его на фиксированное количество цифр.
Итак, допустим, вы создадите имя файла типа:
#size / md5 / name
12345 / aabbccddeeffgghh / foo__DIVIDER__bar__DIVIDER__baz.jpg
Измените его на:
# size /md5 /name
00/00/01/23/45/aa/bb/cc/dd/ee/ff/gg/hh/foo__DIVIDER__bar__DIVIDER__baz.jpg
...и вы ограничили уровень фанаута в любой заданной точке дерева, и таким образом избежали ошибки, о которой идет речь.
На самом деле, чтобы создать дерево имен файлов в этом формате, вы можете выглядеть как:
inDir=/path/to/tree/with/input/files
while IFS= read -r -d '' name; do
sp=$(stat --format=%010s -- "$name") # sp as short for "size padded"
size_dir=${sp:0:2}/${sp:2:2}/${sp:4:2}/${sp:6:2}/${sp:8:2}
{ read -r md5 _ < <(md5sum "$name") && [[ $md5 ]]; } || continue
md5_left=$md5
while [[ $md5_left ]]; do
md5_dir+="/${md5_left:0:2}"
md5_left=${md5_left:2}
done
sep=/
final_name="${size_dir}${md5_dir}/${name//$sep/__DIVIDER__}"
final_dir="${final_name%/*}"
if [[ -d "$final_dir" ]]; then
# Hardlink new file to existing ones (deduplication)
# Be sure to use an archiver that understands hardlinks (not zip)!
existing_files=( "$final_dir"/* )
if [[ -e "${existing_files[0]}" || -L "${existing_files[0]}" ]]; then
ln -- "${existing_files[0]}" "$final_name"
ln -f -- "$final_name" "$file" # and make our input file a hardlink as well
continue
fi
fi
# if we get here, the continue was not invoked
mkdir -p -- "${final_name%/*}"
ln -- "$name" "$final_name"
done < <(find "$inDir" -printf '%P\0')
Конечно, если у вас есть файлы размером более 9,999,999,999 байт, вы захотите добавить дополнительную подкладку (возможно, используя %012s
вместо %010s
, и соответствующим образом изменив вычисление size_dir
).