Как фильтровать файлы при использовании scp для рекурсивного копирования каталога?


99

Мне нужно скопировать все файлы .class с сервера на локальный со всем зарезервированным каталогом. Например server:/usr/some/unknown/number/of/sub/folders/me.class, /usr/project/backup/some/unknown/number/of/sub/folders/me.classпроблема в том, что есть много других бесполезных файлов, таких как файлы .svn-base, которые мне не нужны. как я могу отфильтровать их, чтобы использовать только scpфайлы .class?


Мне нравится упомянутая опция rsync. Вы не упомянули, будет ли это разовая операция или вы будете ее автоматизировать повторно. Для разовой операции разумное использование find, grep -v, xargs и временных файлов поможет с этим быстро справиться.
user47559 04

Ответы:


152

Я бы , наверное , рекомендую использовать что - то вроде rsyncдля этого из - за его includeи excludeфлаги, например: -

rsync -rav -e ssh --include '*/' --include='*.class' --exclude='*' \
server:/usr/some/unknown/number/of/sub/folders/ \ 
/usr/project/backup/some/unknown/number/of/sub/folders/

Еще несколько полезных флагов:

  • -r для рекурсивного
  • -a для архива (в основном все файлы)
  • -v для подробного вывода
  • -e чтобы указать ssh вместо значения по умолчанию (которое на самом деле должно быть ssh)

4
В любом случае, чтобы это игнорировало подпапки, в которых нет * файлов классов? (т.е. мне не нужна куча пустых каталогов)
Грант Берчмайер

круто, и это тоже ужасно быстро!
Прасад Чаласани

2
Можете ли вы объяснить --include, а не --include = На страницах MAN я мог найти объяснение по --include =, но не
--include

1
Опция -aуже включена -rсогласно справочным страницам rsync.
Георг Шелли

3
@GrantBirchmeier --prune-empty-dirsудалит пустые каталоги.
Elrond1337

75

Чтобы исключить точечные файлы из базового каталога:

scp -r [!.]* server:/path/to/something

[!.]* - это глобус оболочки, который расширяется до всех файлов в рабочем каталоге, не начинающихся с точки.


10
Вероятно, это лучший ответ; использование глобусов для фильтрации файлов - лучший способ.
Йошуа Вуйтс

1
Если ваш вариант ограничен scp, как у меня, это определенно помогло.
user28095

3
Это означает, что нужно исключить такие файлы, как запрашиваемые, но как этого добиться для всего каталога?
Пилле

Для zsh:scp -r [\!.]* server:/path/to/something
Майкл Бар-Синай

37

В scp нет функции фильтрации файлов. Для таких «продвинутых» вещей я рекомендую использовать rsync:

rsync -av --exclude '*.svn' user@server:/my/dir .

(эта строка копирует rsync из удаленной папки в текущую)

Последние версии rsync-туннеля по ssh-соединению по умолчанию автоматически.


10

Поскольку вы можете, scpвы должны быть в порядке ssh,
либо напишите следующее, либо войдите и выполните ...

# After reaching the server of interest
cd /usr/some/unknown/number/of/sub/folders
tar cfj pack.tar.bz2 $(find . -type f -name *.class)

вернуться (выйти) на локальный сервер и scp,

# from the local machine
cd /usr/project/backup/some/unknown/number/of/sub/folders
scp you@server:/usr/some/unknown/number/of/sub/folders/pack.tar.bz2 .
tar xfj pack.tar.bz2

Если вы обнаружите, что $(find ...)ваш tar слишком длинный,

find . -type f -name *.class | xargs tar cfj pack.tar.bz2

Наконец, если вы храните его /usr/project/backup/,
зачем беспокоиться об извлечении? Просто сохраните tar.bz2, возможно, с датой + отметкой времени.


Это мне помогло. Я нахожусь в Windows, и я пытаюсь получить rsyncи sshустановить в ОС. Вместо этого это был умный обходной путь. Спасибо!
rayryeng 05

2

Ниже команда для файлов.

scp `find. -maxdepth 1 -name "* .log" \! -name "hs_err_pid2801.log" -type f` root @ IP: / tmp / test /

  1. IP будет IP-адресом целевого сервера.
  2. -name "* .log" для включаемых файлов.
  3. \! -name "hs_err_pid2801.log" для исключения файлов.
  4. . текущий рабочий каталог.
  5. -type f для типа файла.

Команда ниже для каталога.

scp -r `найти. -maxdepth 1 -name "lo *" \! -name "localhost" -type d` root @ IP: / tmp / test /

вы можете настроить указанную выше команду в соответствии с вашими требованиями.


1

При включенной аутентификации на основе ключа ssh будет работать следующий сценарий.

for x in `ssh user@remotehost 'find /usr/some -type f -name *.class'`; do y=$(echo $x|sed 's/.[^/]*$//'|sed "s/^\/usr//"); mkdir -p /usr/project/backup$y; scp $(echo 'user@remotehost:'$x) /usr/project/backup$y/; done

1

Если вы действительно хотите использовать scp, есть косвенный способ. Скажем, мы хотим скопировать весь файл .jpg из локальной папки '/ src' в папку '/ dst' на удаленном сервере 10.1.1.2:

#make a clean temp folder
mkdir /tmp/ttt
#copy all .jpg file and retain folder structure as-is
find /src -type f -name *.jpg -exec cp --parents \{\} /tmp/ttt \;
#copy to remote target folder as-is and retain original time attributes
scp -rp /tmp/ttt/* 10.1.1.2:/dst
#if copy ok, remove temp folder
rm -rf /tmp/ttt

0
scp -i /home/<user>/.ssh/id_rsa -o "StrictHostKeyChecking=no" -rp /source/directory/path/[!.]* <target_user>@<target_system:/destination/directory/path

1
словесные объяснения также полезны вместе с кодом
con

-1
  1. Скопируйте исходную папку в somedir :

    cp -r srcdir somedir

  2. Удалите все ненужные файлы:

    найти somedir -name '.svn' -exec rm -rf {} \ +

  3. запустить scp из somedir


почему все против этого ответа? Это звучит как простое решение вопроса.
bcarroll

7
Потому что это скопирует кучу ненужных файлов, а затем удалит их, потенциально теряя много времени.
Oded

Для программы, которая проходит несколько этапов компиляции, это действительно имеет смысл. Это может происходить прямо перед этапом, на котором скомпилированный код упаковывается в файл tarили zip. Вместо этого сжатия нет (сжатие выполняет scp), и «упакованный» код копируется.
samvv

правда, что @samvv (все зависит от настройки, окружающей среды)
San Jay Falcon

если файлы игнорируются из-за нехватки места, это тратит не только время, но и пространство
Джейк
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.