.png)
Я вижу много вопросов по этому поводу, но не все мои ограничения совпадают, поэтому я начну с них.
Ограничения:
- Я хочу рекурсивно скопировать удаленный каталог.
- Я вообще не могу контролировать настройку удаленного сервера.
- У меня нет прав на запись в этот каталог на удаленной машине.
- Когда я пытаюсь
get -r
, он копирует каталогбез местногоразрешения на запись тоже. - Затем, когда он пытается рекурсивно скопировать вложенные файлы и папки в удаленном каталоге, он получает ошибку вместныйкаталог, в котором мне не дали разрешения на запись.
- Я не могу установить новое программное обеспечение на свой компьютер. (нужно чистое
sftp
решение с «OpenSSH_7.9p1, LibreSSL 2.7.3»)
Вопрос:
Могу ли я рекурсивно копировать удаленные каталоги с помощью pure
sftp
и noместныйошибка разрешений?
решение1
ОБНОВЛЯТЬ: OpenSSH 8.5, выпущенный в 2021-03, устраняет эту проблему; см.http://www.openssh.com/txt/release-8.5в разделе Исправления ошибок пункт для bz#3222.
Примечание: OpenSSH 7.9 был выпущен в 2018-10; он не мог "[появиться] на [a] Mac ~5 лет назад". Вы как-то обновились.
Вы правы; download_dir_internal
in sftp-client.c
создает новый локальный каталог с теми же разрешениями, что и удаленный, если он доступен, за исключением маски 01777 -- т.е. исключая suid и sgid, которые встречаются довольно редко и, скорее всего, не встречаются в вашем случае. Флаг -p
(или -P
) необходим для установки разрешений дляфайлыно игнорируется для каталогов.
Однако, если каталог уже существует, sftp игнорирует ошибку EEXIST. Поэтому, если вы сначала создадите все (пустые) каталогисразрешения на запись и затем сделать get -r
это должно работать. Я не вижу никакого способа в sftp, чтобысписокрекурсивно, поэтому, если вы заранее не знаете структуру каталогов или не знаете, как выполнить что-то find /mydir -type d
на удаленном компьютере, это становится немного некрасивым:
#!/bin/bash # or other location as necessary
REMOTE=(user@host) # array so can add _separated_ options like -i idfile -P port if needed
IFS=$'\n'
all=( )
new=( $( echo ls -n | sftp ${REMOTE[@]} | awk '/^d/{print substr($0,57)}' ) )
while [[ ${#new[@]} -gt 0 ]]; do
all+=( "${new[@]}" )
new=( $( printf "ls -n %s\n" "${new[@]}" \
| sftp ${REMOTE[@]} | awk '/^d/{print substr($0,57)}' ) )
done
mkdir "${all[@]}" # with umask NOT including 200!
# or if (maybe) large enough to hit ARG_MAX
printf '%s\n' "${all[@]}" | xargs mkdir
# if dirnames (can) contain any SP TAB " ' \
# use -d'\n' on GNU but you're on your own otherwise
# (and Macs mostly don't have GNU)
(Не тестировалось на Mac, поскольку у меня его нет, но я считаю, что все здесь переносимо, за исключением отмеченных случаев.)