Я только что задал вопрос, связанный с тем, как я могу считать файлы определенного расширения. Теперь я хочу, чтобы cp
эти файлы новые dir
.
Я пытаюсь,
cp *.prj ../prjshp/
а также
cp * | grep '\.prj$' ../prjshp/
но они дают ту же ошибку,
bash: / bin / cp: список аргументов слишком длинный
Как мне их скопировать?
command-line
files
Sam007
источник
источник
Ответы:
cp *.prj ../prjshp/
это правильная команда, но вы столкнулись с редким случаем, когда она сталкивается с ограничением размера. Вторая команда, которую вы попробовали, не имеет никакого смысла.Один из способов - запускать
cp
файлы по частям. Командаfind
знает, как это сделать:find
рекурсивно пересекает текущий каталог и каталоги под ним.-maxdepth 1
означает останавливаться на глубине 1, т.е. не переходить в подкаталоги.-name '*.prj'
означает работать только с файлами, имя которых соответствует указанному шаблону. Обратите внимание на кавычки вокруг шаблона: он будет интерпретироватьсяfind
командой, а не оболочкой.-exec … {} +
означает выполнить указанную команду для всех файлов. При необходимости он вызывает команду несколько раз, стараясь не превышать лимит командной строки.mv -t ../prjshp
перемещает указанные файлы в../prjshp
. Эта-t
опция используется здесь из-за ограниченияfind
команды: найденные файлы (обозначенные символом{}
) передаются в качестве последнего аргумента команды, вы не можете добавить пункт назначения после него.Другой метод заключается в использовании
rsync
.rsync -r … . ../prjshp
копирует текущий каталог в../prjshp
рекурсивную--include='*.prj' --exclude='*'
означает копировать совпадающие файлы*.prj
и исключать все остальное (включая подкаталоги, поэтому.prj
файлы в подкаталогах не будут найдены).источник
cp * | grep '\.prj$' ../prjshp/
не имеет никакого смысла, но может быть синтаксически допустимой, если*
расширяется до списка файлов с последним, являющимся каталогом (иначеcp SOURCE1 SOURCE2....DEST
). Канал не имеет никакого смысла, конечно, но он также синтаксически действителен в отношении оболочки - он будетdup()
прекрасно работать с файловыми дескрипторами, просто в конце канала чтения не будет никаких данных, потому чтоcp
он не записывает никаких ,Эта команда копирует файлы один за другим и будет работать, даже если их слишком много для
*
развертывания в однуcp
команду:источник
Есть 3 ключевых момента, которые следует иметь в виду при возникновении
Argument list too long
ошибки:Длина аргументов командной строки ограничена
ARG_MAX
переменной, которая по определению POSIX равна "... [m] максимальная длина аргумента для функций exec, включая данные среды" (выделение добавлено) ". То есть, когда оболочка выполняет не Команда -built-it, она должна вызывать одну из них, чтобы вызватьexec()
процесс этой команды, и именно здесьARG_MAX
вступает в игру. Кроме того,/bin/echo
играет роль имя или путь к самой команде (например, ).Встроенные команды оболочки выполняются оболочкой, что означает, что оболочка не использует
exec()
семейство функций и поэтому не подвержена влияниюARG_MAX
переменных.Некоторые команды, такие как
xargs
иfind
знают оARG_MAX
переменной, и многократно выполняют действия в рамках этого ограниченияИз вышеприведенных пунктов и, как показано в превосходном ответе Кусалананды на связанный вопрос, это
Argument list too long
также может произойти, когда обстановка велика. Таким образом, принимая во внимание, что среда каждого пользователя может варьироваться, и размер аргумента в байтах является релевантным, трудно придумать одно количество файлов / аргументов.Как справиться с такой ошибкой?
Главное - сосредоточиться не на количестве файлов, а на том, включает ли команда, которую вы собираетесь использовать,
exec()
семейство функций и тангенциально - пространство стека.Использовать встроенные модули оболочки
Как уже говорилось ранее, встроенные функции оболочки защищены от
ARG_MAX
ограничений, таких какfor
циклы,while
циклы, встроенныеecho
и встроенные функцииprintf
- все они будут работать достаточно хорошо.На связанный вопрос об удалении файлов было решение как таковое:
Обратите внимание, что здесь используется встроенная оболочка
printf
. Если мы вызываем внешнееprintf
, это будет связаноexec()
, следовательно, потерпит неудачу с большим количеством аргументов:массивы bash
Согласно ответу по jlliagre,
bash
не накладывают ограничения на массивах, поэтому строить массив имен файлов и использования срезов каждой итерации петли можно сделать так, как показано на danjpreron в ответе :Это, однако, имеет ограничение быть специфичным для bash и не относящимся к POSIX.
Увеличить пространство стека
Иногда вы можете видеть , что люди предполагают увеличение пространства стека с
ulimit -s <NUM>
; в Linux значение ARG_MAX составляет 1/4 стекового пространства для каждой программы, что означает, что увеличение стекового пространства пропорционально увеличивает пространство для аргументов.Согласно ответу Franck Dernoncourt , который цитирует Linux Journal, можно также перекомпилировать ядро Linux с большим значением для максимального количества страниц памяти для аргументов, однако это больше работы, чем необходимо, и открывает потенциал для эксплойтов, как указано в цитируемой статье Linux Journal.
Избегайте раковины
Другой способ, это использовать
python
илиpython3
которые поставляются по умолчанию с Ubuntu. Пример python + here-doc, приведенный ниже, - это то, что я лично использовал для копирования большого каталога файлов где-то в диапазоне 40000 элементов:Для рекурсивных обходов вы можете использовать os.walk .
Смотрите также:
источник
ИМХО, оптимальными инструментами для работы с ордами файлов являются
find
иxargs
. Смman find
. Смman xargs
.find
с его-print0
переключателем создаетNUL
разделенный список имен файлов (имена файлов могут содержать любой символ execptNUL
или/
), которыйxargs
понимает, используя-0
переключатель.xargs
затем создает самую длинную разрешенную команду (большинство имен файлов, без половины имени файла в конце) и выполняет ее.xargs
повторяет это, покаfind
не предоставит больше имен файлов. Бегxargs --show-limits </dev/null
чтобы увидеть пределы.Чтобы решить вашу проблему, (и после проверки
man cp
найти--target-directory=
):источник