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
опция для размещения заполнителя в любом месте командной строки, при этом передавая как можно больше аргументов одновременно (используя BSDfind
нестандартный-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
)