Выполняя в консоли Linux команду mv или rm, рано или поздно вы можете наткнуться на сообщение об ошибке «argument list too long», используя cp, mv, rm и подобные команды, которые обрабатывают большое количество файлов. Ошибка может возникнуть, если в одном каталоге оказалось много файлов — стремясь экономить память, команда не может обработать полный список и вываливается с ошибкой. Есть несколько возможностей, как обойти данное ограничение.
Для тестов создадим два каталога — «source» и «target» и 20,000 пустых текстовых файлов:
mkdir source mkdir target for i in `seq 1 20000`; do touch source/$i.txt; done
Пытаясь выполнить команды mv, cp, rm или ls над этим количеством наткнемся на ограничение:
mv source/* target/ cp source/* target/ rm source/* ls source/*
Выполнение команд выдаст ошибку:
-bash: /bin/mv: Argument list too long -bash: /bin/cp: Argument list too long -bash: /bin/rm: Argument list too long -bash: /bin/ls: Argument list too long
Чтобы обойти данную проблему, можно использовать xargs или find, либо комбинацию обоих.
Использование ls и xargs для перемещения файлов
Используя вывод команды «ls», можно переместить все файлы из source в target:
ls -1 source | xargs -i mv source/{} target/
Флаг -i в xargs заставит команду подставить вместо {} полученное от предыдущей команды строковое значение. Использовать для вывода команду типа «ls *.txt» нельзя, поскольку список аргументов снова станет слишком большим, прежде чем дойдет до выполнения xargs. Если нужно обработать определенные файлы по маске, лучше использовать команду find.
Использование find для перемещения большого числа файлов из source в target
find source/ -name "*.txt" -exec mv {} target \;
Вместо флага -exec можно использовать xargs:
find source/ -name "*.txt" | xargs -i mv {} target/
Убрав из параметров команды find часть "-name *.txt"
позволит перенести все. Чтобы обработать только файлы, можно использовать параметр «-type f
«.
Все три приведенных примера выполнятся примерно за одинаковое время, возможно вариант с -exec будет чуть быстрее чем xargs.
Использование find для обработки большого числа файлов лучше чем ls, поскольку дает гораздо больше контроля — можно указать шаблон для имен файлов, которые будут обрабатываться.
Как удалить большое число файлов
Приведенные ниже команды позволят удалить любое число файлов, находящихся в директории target:
ls -1 target | xargs -i rm target/{}
find target/ -name "*.txt" -exec rm {} \;
find target/ -name "*.txt" | xargs -i rm {}
Использование приведенных команд выглядит намного сложнее простой «rm -f source/*», но может оказаться единственным вариантом удалить большое число файлов нужного формата.
Спасибо, полезная статья, помогла. Как раз столкнулся с такой проблемой. xargs редко приходится применять, поэтому всё время забывается как по конвейеру передавать аргументы.