Просто чтобы убедиться, что проблема XY не связана, можете ли вы объяснить, почему вы хотите это сделать?
Златовласка
4
@ TAFKA'goldilocks '- у меня много видеофайлов, и я хотел бы проверить качество каждого каталога. Самое маленькое видео даст мне быструю информацию о том, что все остальные файлы тоже плохие.
Нбубис
Ответы:
10
Это делает всю работу за один раз - во всех дочерних каталогах, все в одном потоке без каких-либо проблем с именами файлов. Он будет копировать от самого маленького до самого большого файла, который у вас есть. Вам нужно будет, mkdir ${DESTINATION}если он еще не существует.
find .!-type d -print0 |
du -b0 --files0-from=/dev/stdin |
sort -zk1,1n|
sed -zn 's/^[^0-9]*[0-9]*[^.]*//p'|
tar --hard-dereference --null -T /dev/stdin -cf -|
tar -C"${DESTINATION}"--same-order -xvf -
Вы знаете что, хотя? Чего это не делает, так это пустых дочерних каталогов. Я мог бы сделать некоторое перенаправление по этому конвейеру, но это просто состояние гонки, которое должно произойти. Самый простой, вероятно, лучший. Просто сделайте это потом:
find .-type d -printf 'mkdir -p "'"${DESTINATION}"'/%p"\n'|./dev/stdin
Или, поскольку Жиль очень хорошо указал в своем ответе на вопрос о сохранении разрешений для каталогов, я должен попытаться также. Я думаю, что это сделает это:
@ TAFKA'goldilocks 'Я приму это как комплимент. Огромное спасибо.
mikeserv
15
Вот быстрый и грязный метод с использованием rsync . Для этого примера я рассматриваю что-нибудь под 10 МБ, чтобы быть "маленьким".
Сначала передайте только небольшие файлы:
rsync -a --max-size=10m srcdir dstdir
Затем перенесите оставшиеся файлы. Ранее переданные небольшие файлы не будут повторно скопированы, если они не были изменены.
rsync -a srcdir dstdir
Из man 1 rsync
--max-size=SIZE
This tells rsync to avoid transferring any file that is larger
than the specified SIZE.The SIZE value can be suffixed with a
string to indicate a size multiplier, and may be a fractional
value (e.g."--max-size=1.5m").This option is a transfer rule, not an exclude, so it doesn’t
affect the data that goes into the file-lists, and thus it
doesn’t affect deletions.It just limits the files that the
receiver requests to be transferred.The suffixes are as follows:"K"(or "KiB") is a kibibyte
(1024),"M"(or "MiB") is a mebibyte (1024*1024), and "G"(or
"GiB") is a gibibyte (1024*1024*1024).If you want the multi‐
plier to be 1000 instead of 1024, use "KB","MB", or "GB".(Note: lower-case is also accepted for all values.)Finally,if
the suffix ends in either "+1" or "-1", the value will be offset
by one byte in the indicated direction.Examples:--max-size=1.5mb-1 is 1499999 bytes, and
--max-size=2g+1 is 2147483649 bytes.
Конечно, порядок передачи файлов за файлом не является строго наименьшим, но я думаю, что это может быть простейшее решение, которое соответствует духу ваших требований.
Здесь вы получаете 2 копии жестких ссылок, а софт-ссылки преобразуются в реальные файлы по две копии каждой. Вы бы сделали намного лучше с --copy-dest=DIRи / или --compare-dest=DIRя думаю. Я знаю только потому, что мне пришлось добавить --hard-dereferenceсебя tarпосле публикации моего собственного ответа, потому что я пропускал ссылки. Я думаю, что на rsyncсамом деле ведет себя более специфично для локальных файловых систем с другими - в любом случае я использовал его с USB-ключами, и он заполнил бы шину, если бы я не установил ограничение пропускной способности. Я думаю, что я должен был использовать любой из этих других вместо этого.
mikeserv
1
+1 за "быстрый и грязный метод". Проще обычно лучше, по крайней мере, для целей автоматизации и дальнейшей ремонтопригодности. Я думаю, что это на самом деле довольно чисто. «Элегантный» против «грязный» и «надежный» против «неустойчивый» может иногда вступать в противоречие с целями дизайна, но есть хороший баланс, который можно достичь, и я думаю, что это элегантно и достаточно надежно.
Подстановочный
4
Не cp напрямую, это намного выше его способностей. Но вы можете организовать вызов cpфайлов в правильном порядке.
Zsh позволяет удобно сортировать файлы по размеру с помощью квалификатора glob . Вот фрагмент zsh, который копирует файлы в порядке возрастания размера от нижнего /path/to/source-directoryдо нижнего /path/to/destination-directory.
cd /path/to/source-directory
for x in**/*(.oL);do
mkdir -p /path/to/destination-directory/$x:h
cp $x /path/to/destination-directory/$x:h
done
Вместо цикла вы можете использовать zcpфункцию. Однако сначала нужно создать каталоги назначения, что можно сделать в загадочном документе.
autoload -U zmv; alias zcp='zmv -C'
cd /path/to/source-directory
mkdir **/*(/e\''REPLY=/path/to/destination-directory/$REPLY'\')
zcp -Q '**/*(.oL)''/path/to/destination-directory/$f'
Это не сохраняет владения исходными каталогами. Если вы хотите этого, вам нужно подключить подходящую программу копирования, такую как cpioили pax. Если вы это сделаете, вам не нужно звонить cpили zcpдополнительно.
cd /path/to/source-directory
print -rN **/*(^.)**/*(.oL)| cpio -0-p /path/to/destination-directory
Я не думаю, что есть какой-то способ cp -rсделать это напрямую. Поскольку может пройти неопределенный период времени, прежде чем вы получите волшебное find/ awkрешение, вот быстрый скрипт на Perl:
Использовать этот: ./whatever.pl /src/path /dest/path
Оба аргумента должны быть абсолютными путями ; ~или что-либо еще, что расширяет оболочку по абсолютному пути, это нормально.
Если вы добавите третий аргумент (что угодно, кроме литерала 0), вместо его копирования будет распечатан стандартный отчет о том, что он будет делать, с предварительно добавленными размерами файлов, например
Обратите внимание, что они в порядке возрастания по размеру.
Команда cpв строке 34 является буквальной командой оболочки, так что вы можете делать с переключателями все, что захотите (я просто использовал -aдля сохранения всех характеристик).
File::Findи File::Basenameоба являются основными модулями, т.е. они доступны во всех установках perl.
возможно, это единственный правильный ответ здесь. Или это было ... название - просто изменилось ...? Окно моего браузера называется, cp - copy smallest files first?но название поста просто В copy smallest files first?любом случае, варианты никогда не повредят - это моя философия, но, тем не менее, вы и Дэвид - единственные, кто их использовал, cpи вы единственный, кто их выполнил.
mikeserv
@mikeserv Единственная причина, которую я использовал, cpзаключалась в том, что это самый простой способ сохранить характеристики файла * nix в (кроссплатформенном) Perl. Причина, по которой ваш браузер говорит, cp - заключается в том, что (IMO глупая) функция SE, благодаря которой наиболее популярный из выбранных тегов появляется с префиксом к реальному заголовку.
Златовласка
Хорошо, тогда я снимаю свой комплимент. Не совсем, вы не часто видите pearlвыход из дерева здесь.
mikeserv
1
другой вариант будет использовать cp с выводом из du:
oldIFS=$IFS
IFS=''for i in $(du -sk *mpg | sort -n | cut -f 2)do
cp $i destination
done
IFS=$oldIFS
Это все еще можно сделать в одной строке, но я разделил его, чтобы вы могли прочитать его
Да ... Я продолжаю предполагать, что ни у кого нет новых строк в именах файлов
Дэвид Уилкинс
1
Похоже, что это также не обрабатывает рекурсию через иерархию каталогов, описанную OP.
cpugeniusmv
1
@cpugeniusmv Правильно ... Я как-то пропустил рекурсивную часть .... Я мог бы изменить это для обработки рекурсии, но я думаю, что в этот момент другие ответы делают лучше. Я оставлю это здесь на случай, если это поможет тому, кто видит вопрос.
Ответы:
Это делает всю работу за один раз - во всех дочерних каталогах, все в одном потоке без каких-либо проблем с именами файлов. Он будет копировать от самого маленького до самого большого файла, который у вас есть. Вам нужно будет,
mkdir ${DESTINATION}
если он еще не существует.Вы знаете что, хотя? Чего это не делает, так это пустых дочерних каталогов. Я мог бы сделать некоторое перенаправление по этому конвейеру, но это просто состояние гонки, которое должно произойти. Самый простой, вероятно, лучший. Просто сделайте это потом:
Или, поскольку Жиль очень хорошо указал в своем ответе на вопрос о сохранении разрешений для каталогов, я должен попытаться также. Я думаю, что это сделает это:
Я был бы готов поспорить, что это быстрее, чем в
mkdir
любом случае.источник
Вот быстрый и грязный метод с использованием
rsync
. Для этого примера я рассматриваю что-нибудь под 10 МБ, чтобы быть "маленьким".Сначала передайте только небольшие файлы:
rsync -a --max-size=10m srcdir dstdir
Затем перенесите оставшиеся файлы. Ранее переданные небольшие файлы не будут повторно скопированы, если они не были изменены.
rsync -a srcdir dstdir
Из
man 1 rsync
Конечно, порядок передачи файлов за файлом не является строго наименьшим, но я думаю, что это может быть простейшее решение, которое соответствует духу ваших требований.
источник
--copy-dest=DIR
и / или--compare-dest=DIR
я думаю. Я знаю только потому, что мне пришлось добавить--hard-dereference
себяtar
после публикации моего собственного ответа, потому что я пропускал ссылки. Я думаю, что наrsync
самом деле ведет себя более специфично для локальных файловых систем с другими - в любом случае я использовал его с USB-ключами, и он заполнил бы шину, если бы я не установил ограничение пропускной способности. Я думаю, что я должен был использовать любой из этих других вместо этого.Не
cp
напрямую, это намного выше его способностей. Но вы можете организовать вызовcp
файлов в правильном порядке.Zsh позволяет удобно сортировать файлы по размеру с помощью квалификатора glob . Вот фрагмент zsh, который копирует файлы в порядке возрастания размера от нижнего
/path/to/source-directory
до нижнего/path/to/destination-directory
.Вместо цикла вы можете использовать
zcp
функцию. Однако сначала нужно создать каталоги назначения, что можно сделать в загадочном документе.Это не сохраняет владения исходными каталогами. Если вы хотите этого, вам нужно подключить подходящую программу копирования, такую как
cpio
илиpax
. Если вы это сделаете, вам не нужно звонитьcp
илиzcp
дополнительно.источник
Я не думаю, что есть какой-то способ
cp -r
сделать это напрямую. Поскольку может пройти неопределенный период времени, прежде чем вы получите волшебноеfind
/awk
решение, вот быстрый скрипт на Perl:Использовать этот:
./whatever.pl /src/path /dest/path
Оба аргумента должны быть абсолютными путями ;
~
или что-либо еще, что расширяет оболочку по абсолютному пути, это нормально.Если вы добавите третий аргумент (что угодно, кроме литерала
0
), вместо его копирования будет распечатан стандартный отчет о том, что он будет делать, с предварительно добавленными размерами файлов, напримерОбратите внимание, что они в порядке возрастания по размеру.
Команда
cp
в строке 34 является буквальной командой оболочки, так что вы можете делать с переключателями все, что захотите (я просто использовал-a
для сохранения всех характеристик).File::Find
иFile::Basename
оба являются основными модулями, т.е. они доступны во всех установках perl.источник
cp - copy smallest files first?
но название поста просто Вcopy smallest files first?
любом случае, варианты никогда не повредят - это моя философия, но, тем не менее, вы и Дэвид - единственные, кто их использовал,cp
и вы единственный, кто их выполнил.cp
заключалась в том, что это самый простой способ сохранить характеристики файла * nix в (кроссплатформенном) Perl. Причина, по которой ваш браузер говорит,cp -
заключается в том, что (IMO глупая) функция SE, благодаря которой наиболее популярный из выбранных тегов появляется с префиксом к реальному заголовку.pearl
выход из дерева здесь.другой вариант будет использовать cp с выводом из du:
Это все еще можно сделать в одной строке, но я разделил его, чтобы вы могли прочитать его
источник