Вы не можете сделать это с помощью простого удаленного -- -удаленного SCP [1].
Вместо этого подключитесь по ssh к 1-му удаленному хосту и оттуда запустите scp с аргументом порта:
ssh -p 2222 ruser1@rhost1 scp -P 2222 /rpath/1 ruser2@rhost2:/rpath/2
Если вы хотите делать именно то, что делает scp
, вы также можете добавить опции -n -x -oClearAllForwardings=yes
к ssh
, хотя обычно это не требуется.
[1] :более новые версии scp
поддерживают спецификацию uri (, включающую порт )вместо host:path
, но только при использовании опции -3
(«проходить через локальный хост» ).
Вероятно, вы могли бы использовать
scp -3 -P 2222 ruser1@rhost1:/rpath/1 scp://ruser2@rhost2:2222//rpath/2
(обратите внимание, что /
после host[:port]
не является частью пути --scp://user@host/file
, будет ссылаться на ./file
в домашнем каталоге user
).
Но копирование через локальный хост происходит медленнее, и, по моему опыту, оно скроет ошибки. Например, это не будет печатать никаких сообщений об ошибках, несмотря на невозможность создать файл /foo/bar/baz
:
.
scp -3 localhost:.bashrc localhost:/foo/bar/baz
Я не углублялся в это --просто избегал этого;-)
Если кого-то все это не убедило, они могут посмотреть исходный код:
void
toremote(char *targ, int argc, char **argv)
{
...
} else if (host) { /* standard remote to remote */
if (tport != -1 && tport != SSH_DEFAULT_PORT) {
/* This would require the remote support URIs */
fatal("target port not supported with two "
"remote hosts without the -3 option");
}
Обратите внимание, что переменная tport
устанавливается только путем синтаксического анализа scp://
uri и просто не существует в версиях старше 7.6p1 (Октябрь 2017 ).
Два варианта вашего кода, каждый из которых передает специальные значения в строчный скрипт -, который вы вызываете изfind
:
#!/bin/sh
mpath=$1
fn_name=$2
fn_arg=$3
find "$mpath" -type d -exec sh -c '
cd "$3" && /path/to/my/script.sh "$1" "$2"' sh "$fn_name" "$fn_arg" {} \;
Когда каталог найден, find
просто передает значения двух переменных fn_name
и fn_arg
в сценарий sh -c
в качестве двух первых аргументов перед аргументом пути к каталогу. Внутри скрипта мы используем два первых аргумента в качестве аргументов вашего скрипта, а третий — в качестве пути к каталогу cd
.
Обратите внимание, что $0
будет содержать строку sh
. Оболочка будет использовать эту (произвольную )строку в любых сообщениях об ошибках, которые она может выдать (вы показываете пример этого в своем вопросе ). Значение $0
является , а не частью списка позиционных параметров.
Другой вариант, который вызывает внутристрочный скрипт -с максимально возможным количеством путей к каталогам одновременно:
#!/bin/sh
mpath=$1
fn_name=$2
fn_arg=$3
find "$mpath" -type d -exec sh -c '
fn=$1 arg=$2; shift 2
for dirpath do
( cd "$dirpath" && /path/to/my/script.sh "$fn" "$arg" )
done' sh "$fn_name" "$fn_arg" {} +
Изменив \;
на +
в конце команды find
, мы вызываем sh -c
с пакетами найденных путей к каталогам. Сценарий строки -затем должен перебирать их и вызывать ваш сценарий для каждого по очереди.
Скрипт строки -начинается с выбора имени функции и аргумента из списка позиционных параметров и смещения их из этого списка. Затем он перебирает оставшиеся аргументы и вызывает cd
и ваш скрипт для каждого.Ниже приведен строчный скрипт -со вставленным небольшим количеством воздуха :
fn=$1 # 1st argument from find
arg=$2 # 2nd argument from find
shift 2 # remove them from the list
# Iterate over the remaining arguments
for dirpath do
( cd "$dirpath" && /path/to/my/script.sh "$fn" "$arg" )
done
Я запускаю тело цикла в оболочке sub -, чтобы избежать «cd
возврата» каждый раз после запуска сценария.
Здесь я использую sh
, а не bash
, так как sh
ничего не нужно для запуска этого кода. Кроме того, показанные здесь команды find
используют только стандартные функции.
Вот мое предложенное (и рабочее )решение:
#!/bin/bash
function_name=$1
mpath="$2"
marg=$3
while IFS= read -r -d '' sdir
do
cd "$sdir"
/path/to/my/script.sh "$function_name" "$marg"
done < <(find "$mpath" -type d -print0)
Изменить :В ответ на комментарии, это решение не работает с относительными путями.