Bash: не использовать find -exec

Когда используешь scp или же rsync Мне часто не удается справиться с ошибкой "Список аргументов слишком длинный". Когда приходится mv или же rmУ меня нет проблем в использовании find а также xargs но я не понимаю, как использовать find а также -exec несмотря на все сообщения SE на эту тему. Рассмотрим следующую проблему...

Я старался

$scp /Path/to/B* Me@137.92.4.152:/Path/to/

-bash: /usr/bin/scp: Argument list too long

Так я попробовал

$find . -name "/Path/to/B*" -exec scp "{}" Me@137.92.4.152:/Path/to/ '\;'

find: -exec: no terminating ";" or "+"

поэтому я попробовал

$find . -name "/Path/to/B*" -exec scp "{}" Me@137.92.4.152:/Path/to/ ';'

find: ./.gnupg: Permission denied
find: ./.subversion/auth: Permission denied

Так я попробовал

$sudo find . -name "/Path/to/B*" -exec scp "{}" Me@137.92.4.152:/Path/to/ ';'

и ничего не происходит, я ввожу свой пароль

Я на Mac OSX версии 10.11.3, терминала версии 2.6.1

3 ответа

Решение

Полезный ответ Р. Сабана решает вашу главную проблему:

  • -name принимает только шаблон имени файла, но не шаблон пути.

  • В качестве альтернативы, вы можете просто использовать -path первичный вместо -name первична.

Что касается использования как можно меньше вызовов scp насколько это возможно - для каждого из них требуется указать пароль по умолчанию:

  • В качестве альтернативы рассмотрите возможность обхода использования scp в целом, как подсказывает полезный ответ Эрика Ренуфа.

  • В то время как find "s -exec Первичный позволяет использовать терминатор + вместо ; (который должен быть передан как ';' или же \; предотвратить интерпретацию оболочки ; как терминатор команды) для передачи столько имен файлов, сколько поместится в одной командной строке (встроенный xargs в некотором смысле), это не вариант здесь, потому что использование + требует этого заполнителя {} последним в командной строке, непосредственно перед +,

  • Тем не менее, поскольку вы находитесь на MacOS, вы можете использовать BSD xarg нестандартный -J опция для размещения заполнителя в любом месте командной строки, при этом передавая как можно больше аргументов одновременно (используя BSD find нестандартный -print0 вариант в сочетании с xargs нестандартный -0 опция гарантирует, что все имена файлов передаются как есть, даже если они имеют встроенные пробелы, например):

find . -path "/Path/to/B*" -print0 | xargs -0 -J {} scp {} Me@137.92.4.152:/Path/to/

Теперь самое большее вам будет предложено несколько раз: одна подсказка для каждой группы аргументов, как требуется для размещения всех аргументов при соблюдении макс. длина командной строки с наименьшим количеством возможных вызовов.

РЕДАКТИРОВАТЬ после вашего обновления:

find "/Path/to" -maxdepth 1 -name "B*" -exec scp {} Me@137.92.4.152:/Path/to/ \;

Решение, которое не требует многократного scp Соединения (и, следовательно, записи пароля) должны быть tar с одной стороны и unar с другой, например:

find /Path/to -maxdepth 1 -name 'B*' -print0 | tar -c --null -T - | ssh ME@137.92.4.152 tar -x -C /Path/to

при условии, что ваша версия find опоры -print0 и тому подобное. Это работает, распечатывая нулевой завершенный список файлов из find и рассказывать tar прочитать свой список файлов из stdin (-T -) обработка списка как завершенного нуля (--null) и создайте новый архив (-c). По умолчанию, tar напишет в стандартный вывод.

Итак, мы передадим этот архив в ssh Команда на целевой хост. Это будет читать вывод предыдущей команды на ее стандартном вводе, поэтому мы будем использовать tar там извлечь (-x) архив в данный каталог (-C /Path/to)

Другие вопросы по тегам