У меня есть миллионы изображений на моем облачном сервере Ubuntu. Когда я перемещаю всю папку, содержащую 12 миллионов изображений, используя mv
команду, это происходит почти мгновенно. Однако, когда я mv
только изображения (не папки), это занимает некоторое время. Есть ли способ перемещать все изображения так же быстро, как папки?
Вот что происходит:
В папке src 12 миллионов изображений, и я перемещаю это в папку dst, используя
$ mv src ../dst
Происходит сразу
Внутри папки src я делаю это для перемещения:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ {} +
Это займет некоторое время.
Есть ли способ ускорить второй процесс?
dst
находится в разделе, тогда как../../dst
находится на другом.{}
аргумента, где имя файла (ов) будет расширен.find
.find ... -exec mv -t ../../dst/ {} \;
будет вызыватьmv
один раз за файл;find ... -exec mv -t ../../dest {} +
было бы намного быстрее, копируя столько файлов за вызов, сколько возможно, но все же не так быстро, как перемещение самой директории, как объясняет dadexix86 .Ответы:
TL; DR : нет
Для меньшего количества файлов вам это не понадобится,
find
но даже в этом упрощенном и меньшем случае, если вы простоэто займет больше времени, чем перемещение всего каталога за один раз.
Зачем? Дело в том, чтобы понять, что
mv
делает.Вкратце,
mv
перемещает число (которое идентифицирует каталог или файл) из inode (каталог, содержащий его) в другой, и эти индексы обновляются в журнале файловой системы или в FAT (если файловая система). реализован таким образом).Если источник и пункт назначения находятся в одной файловой системе, фактическое перемещение данных отсутствует, оно просто меняет положение, точку, к которой они присоединены.
Таким образом, когда вы
mv
один каталог, вы делаете эту операцию один раз .Но когда вы перемещаете 1 миллион файлов, вы выполняете эту операцию 1 миллион раз .
Чтобы дать вам практический пример, у вас есть дерево с множеством ветвей. В частности, есть один узел, к которому прикреплено 1 миллион веток.
Чтобы вырезать эти ветви и переместить их в другое место, вы можете вырезать каждый из них, чтобы сделать 1 миллион разрезов, или вырезать непосредственно перед узлом, таким образом, делая только один разрез (в этом разница между перемещением файлов и каталог).
источник
mv
той же файловой системе это просто перезапись записи TOC.mv *.jpg
вероятно, потерпит неудачу для 12 миллионов файлов, поэтому он использует find. Я полагаю, что большинство Unix, включая Linux (если кто-то не изменял его за последние 5-10 лет), имеют ограниченную максимальную длину командной строки. Я думаю, что это было 64K для Linux в течение длительного времени. То же самое ограничение применяется к переменным среды, я почти уверен.Это все равно будет медленным, потому что, как отмечалось, файловая система должна заново связать каждое имя файла с новым местоположением.
Тем не менее, вы можете ускорить его с того, что у вас есть сейчас.
Ваша команда find запускает exec один раз для каждого файла. Таким образом, он запускает
mv
команду 12 миллионов раз для 12 миллионов файлов. Это можно улучшить двумя способами.Добавьте плюс в конце:
find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/ +
проверьте страницу руководства, чтобы убедиться, что она поддерживается в вашей версии
find
. Эффект должен состоять в том, чтобы запустить сериюmv
команд с таким количеством имен файлов, которое поместится в каждой командной строке.Используйте
find
иxargs
вместе.find -maxdepth 1 -name '*.jpg' -print0 | xargs -0 mv -t ../../dst/
Для
-print0
разделения имен файлов будет использоваться NUL, то есть нулевые байты. Этот плюсxargs -0
устраняет любые проблемы,xargs
которые в противном случае имели бы пробелы в именах файлов. Командаxargs
прочитает список имен файлов изfind
команды и запуститmv
команду с тем количеством имен файлов, которое подходит.источник
Ваша путаница возникает из-за абстракции файловой системы, которая заставляет вас верить, что папка содержит файлы и другие папки в виде дерева. На самом деле это не так: все файлы и каталоги в файловой системе расположены на одном уровне и идентифицируются с помощью номеров какого-либо рода, в зависимости от реализации. Каталоги - это просто специальные файлы, которые содержат списки других файлов.
Когда вы «перемещаете» файлы внутри файловой системы, реальные файлы никуда не уходят. Скорее, списки внутри каталогов обновляются для отражения изменений.
mv src ../dst
перемещает одну запись списка из каталога.
в каталог../dst
, так что это быстро.find -maxdepth 1 -name '*.jpg' -exec mv -t ../../dst/
приходится перемещать миллионы записей, поэтому это медленнее. Это может быть ускорено, если вы вызываетеmv
только один раз, а не один раз для файла, и самаmv
команда может быть оптимизирована для перемещения нескольких записей каталога за один шаг, но нет способа сделать это так же быстро, как при перемещении одного каталога ,источник
Упрощенный ответ
перемещение файла выполняется за 3 шага:
этот процесс одинаков для файла или папки.
и очевидно, что сделать это для 1 файла на 100 быстрее, чем для 100 файлов.
man link
is add ()man unlink
это удаление ()mv
просто использует эти две команды выше и добавляет промежуточную проверку для предотвращения потери данных.источник