Рекурсивное копирование удаленных SFTP-каталогов без прав записи (на локальные)

Рекурсивное копирование удаленных SFTP-каталогов без прав записи (на локальные)

Я вижу много вопросов по этому поводу, но не все мои ограничения совпадают, поэтому я начну с них.

Ограничения:

  • Я хочу рекурсивно скопировать удаленный каталог.
  • Я вообще не могу контролировать настройку удаленного сервера.
  • У меня нет прав на запись в этот каталог на удаленной машине.
  • Когда я пытаюсь 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_internalin 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, поскольку у меня его нет, но я считаю, что все здесь переносимо, за исключением отмеченных случаев.)

Связанный контент