У меня есть папка с именем test, в которой находятся только файлы jpeg. Тысячи файлов. Мне нужно поместить эти тысячи файлов с именами типа 1.jpg, 2.jpg... 345623.jpg в подпапки с именами типа 001000, 002000, каждая из которых будет содержать 1000 файлов. Поэтому мне нужно переместить все файлы jpg из папки test в подпапки, содержащие по 1000 файлов jpg, наиболее эффективным способом.
На данный момент у меня есть следующее:
i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n1000)
решение1
find . -type f \
| split -l 1000 -a 3 --numeric-suffixes=1 \
--filter='target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"' \
- ''
Объяснение:
find . -type f
находит файлы (также в подкаталогах, но я полагаю, что в вашем случае подкаталогов пока нет).split -l 1000 -a 3 --numeric-suffixes=1 ... - ''
считывает данные со своего stdin (-
) и разбивает данные на порции, каждая из которых имеет длину 1000 строк (-l 1000
). Каждой порции соответствует «имя», состоящее из пустого префикса (''
) и числового суффикса, начинающегося с 1 (--numeric-suffixes=1
) и имеющего длину 3 (-a 3
). Фактически на данный момент имена имеют вид001
,002
и так далее.--filter=...
запускает указанную команду отдельно для каждого фрагмента, соответствующее имя доступно как$FILE
. Команда для запуска -target="${FILE}000"; mkdir "$target" && xargs -d "\n" mv -t "$target"
target="${FILE}000"
преобразует имя, например001
или002
в желаемое имя будущего каталога (001000
или002000
и т.п.), и сохраняет его вtarget
переменной.mkdir "$target"
создает новый каталог с желаемым именем.xargs -d "\n" ...
считывает весь фрагмент (1000 путей к файлам или меньше в последнем фрагменте) и использует каждую целую строку (в качестве разделителя используется новая строка:-d "\n"
) в качестве аргумента для следующей команды.mv -t "$target"
перемещает объекты (переданныеxargs
) во вновь созданный каталог.
Примечания:
- Команда не заботится об именах файлов.
345623.jpg
не обязательно попадет в346000/
. Возможные причины:find
не сортирует; но даже если вы поместитеsort -n
междуfind
иsplit
, это может быть...- имеются пробелы в нумерации.
split
в любом случае потребуется 1000 записей (если это не последний фрагмент; если так, то 1000 или меньше).
mkdir ... && xargs ...
не запуститсяxargs
в случаеmkdir
сбоя (будьте осторожны с существующими каталогами).- Используйте
cp -l -t "$target"
вместоmv -t "$target"
для создания жестких ссылок в каталогах, оставляя уже существующие записи в текущем каталоге нетронутыми. Таким образом, если что-то пойдет не так, простоrm -r
каталоги и начните заново. Сmv
, если задача будет прервана, вы в конечном итоге переместите некоторые файлы, а некоторые нет; это может быть беспорядок. - Я думаю,
-a 3
что не пропустит вас999
(999000
после добавления конечных нулей). Еслиsplit
нужно создать больше фрагментов, он даст сбой в середине своей работы. По этой причине убедитесь,999
что этого достаточно, прежде чем запускать команду. - Имена с символами новой строки нарушат работу кода (в целом имена файлов выглядят нормально).