Як відфільтрувати файли при використанні scp для копіювання режиму рекурсивно?


99

Мені потрібно скопіювати всі .class файли з сервера на локальний з усіма зарезервованими dir. Наприклад 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. Ви не згадали, чи це разова операція, чи ви будете автоматизувати це повторно. Для разової операції розумне використання знахідки, grep -v, xargs та тимчасових файлів повинно зробити це короткою роботою.
user47559

Відповіді:


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
У будь-якому випадку зробити це ігнорувати вкладені папки, в яких немає файлів класу *? (тобто я не хочу купу порожніх папок)
Грант Бірчмаєр

дивовижно, і це теж зле швидко!
Prasad Chalasani

2
Чи можете ви пояснити --include, not --include = На сторінках MAN я можу знайти пояснення на --include = але не --include
bazz

1
Опція -aвже включає в себе -rвідповідно до сторінок man rsync.
Георг Шеллі

3
@GrantBirchmeier --prune-empty-dirsвидалить порожні записи.
Elrond1337

74

Щоб виключити точкові файли в базовому каталозі:

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

[!.]* це глобус оболонки, який розширюється до всіх файлів у робочому каталозі, не починаючи з крапки.


10
Це, мабуть, найкраща відповідь; використання глобусів для фільтрації файлів - це шлях.
Йошуа Вуйтс

1
Якщо ваш вибір обмежений до scp, як і я, це, безумовно, допомогло.
user28095

3
Це вказує на виключення файлів, як запитується, але як цього можна досягти для цілого каталогу?
Pille

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 ...)занадто довгий час для зміни вашої смоли,

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

Нарешті, оскільки ви це тримаєте /usr/project/backup/,
навіщо турбувати видобуток? Просто збережіть tar.bz2, з позначкою дати та часу.


Це мені допомогло. Я в Windows, і я борюся, намагаючись отримати rsyncта sshвстановити на ОС. Натомість це було розумне обхідне рішення. Дякую!
rayryeng

2

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

scp `знайти. -maxdepth 1 -назву "* .log" \! -name "hs_err_pid2801.log" -тип f` root @ IP: / tmp / test /

  1. IP буде IP адресою сервера призначення.
  2. -name "* .log" для файлів, що включають.
  3. \! -name "hs_err_pid2801.log" для виключення файлів.
  4. . поточний робочий реж.
  5. -тип f для типу файлу.

Нижче команда для каталогу.

scp -r `знайти. -maxdepth 1 - ім'я "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
словесні пояснення також корисно разом з кодом
кін

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

    cp -r srcdir somedir

  2. Видаліть усі непотрібні файли:

    знайти somedir -ім'я '.svn' -exec rm -rf {} \ +

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


чому всі голоси проти цієї відповіді? Це звучить як проміжне рішення питання.
bcarroll

7
Оскільки це скопіює купу непотрібних файлів, а потім видалить їх, втрачаючи потенційно багато часу.
Почато

Для програми, яка проходить кілька етапів компіляції, це насправді має великий сенс. Це може йти безпосередньо перед кроком, який пакує скомпільований код у файл tarабо zip-файл. Натомість стиснення не відбувається (компресію виконує scp), а "упакований" код копіюється.
samvv

правда, що @samvv (все залежить від налаштування, середовища)
San Jay Falcon

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