Проблема в безопасном копировании (scp) имена файлов с пробелами

Во-первых, Вы правы подозревать, что “все данные” не означают целый файл. На самом деле тот слой файловой системы воздействует на блоки файла фиксированного размера, не на целые файлы. На том уровне важно сохранить ограниченный объем данных, таким образом работая над целыми файлами (который может быть произволен большой), не работал бы.

Во-вторых, в Вашем вопросе существует неправильное представление. Поведение журналирования не что-то, что можно наблюдать путем рассмотрения содержания каталога с ls, это работает на намного более низком уровне. С нормальными инструментами Вы будете всегда видеть, что файл там. (Это было бы катастрофически, если создание файла, казалось, не, y'know, создало его.), Что происходит под капотом, то, что файл может храниться по-разному. Сначала, первые несколько блоков сохраняются в журнале. Затем как только эффективно возможно, данные перемещены в его заключительное местоположение. Это - все еще тот же файл в том же каталоге, просто сохраненном по-другому.

Единственным путем можно заметить, что поведение журналирования состоит в том, если Вы навещаете точно, что ядро пишет в диск, или если Вы анализируете дисковое содержание после катастрофического отказа. В нормальном функционировании журнал является деталью реализации: если бы Вы видели его в действии (кроме мудрого производительностью), то это было бы сильно повреждено.

Для получения дополнительной информации о журналах файловой системы, я рекомендую запуститься со статьи Wikipedia. В терминах ext3, a data=journal гарантирует, что, если система отказывает, каждый файл находится в состоянии, которое это имело в какой-то момент перед катастрофическим отказом (это - не всегда последнее состояние из-за буферизации). Причина этого не происходит автоматически, состоит в том, что ядро переупорядочивает записи на диск для эффективности (это может иметь большое значение). Это называют “физическим журналом” в статье Wikipedia. Другие два режима (data=ordered и data=writeback) формы “логического журнала”: они быстрее, но они могут привести к поврежденным файлам. Журнал ограничивает риск повреждения в несколько файлов, содержащих мусор; ext3 всегда использует полный журнал для метаданных. Без журнала для метаданных метаданные могут потеряться, ведя к основному повреждению файловой системы. Кроме того, без журнала, восстановление после того, как катастрофический отказ требует полной проверки целостности файловой системы, тогда как с журналом восстановление означает воспроизводить несколько записей журнала.

Обратите внимание, что даже с журналом, типичные файловые системы Unix не гарантируют глобальной непротиворечивости файловой системы, только непротиворечивость на файл самое большее. Таким образом, предположите, что Вы пишете в файл foo, затем Вы пишете в файл bar, затем системные катастрофические отказы. Это возможно для bar иметь новое содержание, но foo все еще иметь старое содержание. Чтобы иметь полную непротиворечивость, Вам нужна транзакционная файловая система.

8
06.02.2012, 16:22
3 ответа

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

scp -r -P 8484 root@172.31.72.103:"'/media/New Volume/lj'" /home/pratheep
scp -r -P 8484 root@172.31.72.103:'"/media/New Volume/lj"' /home/pratheep

или использование справки заполнения клавишей Tab

scp -r -P 8484 root@172.31.72.103:/media/New\\\ Volume/lj /home/pratheep
17
27.01.2020, 20:09
  • 1
    Полезно отметить это scp использование ssh как его транспорт, который объясняет, почему существует две передачи случая интерпретации оболочки. –  msw 06.02.2012, 16:47

scp и rsync передайте удаленные имена файлов удаленной оболочке. Это позволяет Вам передавать шаблоны, как в

scp remotehost:'*.txt' .

но это имеет противное последствие, что Вам нужно дополнительное заключение в кавычки при предоставлении удаленного имени файла.

Можно передать -s опция к rsync заставить его защитить имена файлов от расширения удаленной оболочкой. Но это включает встроенное подстановочное расширение rsync, таким образом, все еще необходимо заключить в кавычки \[?*.

Обходное решение должно передать архив:

ssh -P 8484 root@172.31.72.103 'cd "/media/New Volume" && tar cf - lj' |
tar xf - -C /home/pratheep

Другой метод должен смонтировать удаленную файловую систему и затем использовать обычные инструменты для выполнения копии.

mkdir mnt
sshfs -p 8484 root@172.31.72.103:/ mnt
cp -Rp 'mnt/media/New Volume/lj' /home/pratheep
fusermount -u mnt
rmdir mnt
1
27.01.2020, 20:09

Я столкнулся с похожими проблемами при попытке скопировать файлы с удаленных путей, содержащих пробелы, с помощью scpиз сценария Bash.

Вот решения, которые я придумал:

Пути эвакуации вручную:

scp user@host:'dir\ with\ spaces/file\ with\ spaces' <destination>
scp user@host:"dir\\ with\\ spaces/file\\ with\\ spaces" <destination>
scp user@host:dir\\\ with\\\ spaces/file\\\ with\\\ spaces <destination>

Примечание :не требует опции -T(, см. ниже ).

Использование двойных -кавычек + опция-T:

scp -T user@host:"'<path-with-spaces>'" <destination>
scp -T user@host:'"<path-with-spaces>"' <destination>
scp -T user@host:"\"<path-with-spaces>\"" <destination>

Обратите внимание, что :без опции -T, эти команды приведут к protocol error: filename does not match request. Причина этого подробно обсуждается здесь .

Путь выхода с помощью printf:

source="<path-with-spaces>"
printf -v source "%q" "${source}"
scp user@host:"${source}" <destination>

Обратите внимание, :это прекрасно работает без опции -T, но только для одного файла. Для нескольких файлов снова требуется опция -T(та же ошибка, что и выше ).

0
14.10.2021, 19:40

Теги

Похожие вопросы