Рекурсивное копирование скрытых файлов - Linux

19

Есть ли простой способ рекурсивного копирования всех скрытых файлов в каталоге в другой каталог? Я хотел бы сделать резервную копию только всех файлов настроек в домашнем каталоге, а не обычных файлов. Я старался:

cp -R .* directory

но он распознает .и ..и рекурсивно копирует все не скрытые файлы тоже. Есть ли способ заставить cp игнорировать .и ..?

Zifre
источник
Есть ли разница между -rи -R?
Чаминда Бандара

Ответы:

15

Моим любимым ходом режиссеров вообще было:

tar cvf - . | (cd /dest/dir; tar xvf -)

который подключает текущий каталог к ​​стандартному выводу, а затем направляет его в подоболочку, которая сначала переписывает компакт-диск в конечный каталог перед тем, как распаковать стандартный ввод. Простой, прямой, расширяемый - подумайте, что происходит, когда вы заменяете () ssh на другой компьютер. Или, чтобы ответить на ваш вопрос, вы можете сделать:

tar cvf - .* --exclude=\. --exclude=\.\. | (cd /dest/dir; tar xvf -)
pjz
источник
1
Спасибо, опция исключения - это то, что мне нужно. Я уже сделал это по-другому, но я оставлю это для дальнейшего использования. Это кажется действительно гибким (хотя, может быть, медленнее).
Zifre
1
Хороший совет. У меня есть пара улучшений: 1) Использование cd /dest/dir && tar xvf -. &&Остановит вас от blatting по каталогу источника , если у вас есть опечатка в пункте назначения. 2) Вам нужен только vфлаг tar для одной из команд tar (или ни одной).
Том Шоу
Справедливо. Мне также известно, что можно группировать вещи другим способом: скопировать сюда удаленный srcdir, сделайте(cd /src/dir && tar cf - .) | tar xvf -
pjz
17

Почти каждый раз, когда это можно решить просто с помощью:

cp -R .[a-zA-Z0-9]* directory

Довольно необычно иметь скрытый файл, который не начинается с одного из этих символов.

Другие сопоставления с образцами доступны ( .??*, .[^.]*) - см. Комментарии

Альнитак
источник
Это будет игнорировать только.-Xyz - материал в [] соответствует только первому символу после точки.
Хэмиш Даунер
6
. [^.] * поймал бы все
фальстро
1
... кроме вещей, начинающихся с двух периодов.
Falstro
@roe - это тоже хорошая версия
Alnitak
@mish - да, я сказал так же в ответе.
Альнитак,
11

Вы могли бы использовать rsync.

rsync -a ./ /some/other/directory/

который скопирует содержимое текущего каталога (включая точечные файлы, но не включая ..)

Рори
источник
Простой и работает для скрытых файлов в скрытых папках тоже.
user59183
для меня это менее запутанный и самый эффективный из предоставленных решений
palerdot
Хорошее решение. Я также нуждался в этом, чтобы не копировать через .gitкаталоги. Добавление -C делает это, и поэтому команда становится:rsync -aC ./ /some/other/directory/
Theruss
10

Я умоляю вас, шаг от простого расширения оболочки в cpкомандной строке - оболочка расширение имеет все виды гм . «Интересных» угловые случаи (нежелательных рекурсию , вызванные и .., пробела, непечатаемые вещи, жесткие ссылки, символические ссылки, и и т. д.) Используйте findвместо этого (он входит в findutilsпакет, если он у вас не установлен - что было бы странно, все дистрибутивы устанавливают его по умолчанию):

find -H /path/to/toplevel/dir/ -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec cp -a '{}' /path/to/destination/dir/ \;

Пошаговое объяснение:

  • -Hприведет к тому, что findне будет следовать символическим ссылкам (кроме случаев, когда фактическое имя каталога верхнего уровня, которое вы дали, является символической ссылкой; это будет следовать.)
  • /path/to/toplevel/dir/ Очевидно, что он должен быть заменен вами путем к каталогу, в котором находятся файлы настроек и каталоги, резервные копии которых вы хотите создать.
  • -maxdepth 1остановит findрекурсивный спуск в любые каталоги, имя которых начинается с точки. Нам не нужно это повторять, cpмы сделаем это за нас, нам просто нужны имена на этом уровне.
  • -name '.*'говорит, findчто мы хотим, чтобы все имена начинались с точки. Это не будет работать правильно, если установлена ​​переменная окружения POSIXLY_CORRECT, но редко (если вообще когда-либо). Это первое условие соответствия, которое мы указали до сих пор.
  • a \( ....... \)является и сопровождается более сложным условием в скобках (я использовал ..... для его замены, это объяснено ниже.) Нам нужно избегать скобок, так как иначе они будут (неправильно) интерпретироваться оболочкой, отсюда и обратный слеш перед ними,
  • -type d -o -type f -o -type lтри условия с или между ними. -type dсопоставляет каталоги, -type fсопоставляет обычные файлы и -type lсопоставляет символические ссылки. Вы можете выбрать то, что вы хотите - например, если вы не хотите делать резервные копии каталогов настроек, опустите -type d( -oочевидно, и справа за ним).
  • -exec ..... \;говорит findвыполнить команду каждый раз, когда встречается совпадение. Конец команды отмечен точкой с запятой, которую мы снова должны экранировать обратной косой чертой, чтобы избежать интерпретации оболочки. В этой командной строке вам нужно использовать, {}где вы хотите, чтобы имя встречающегося в данный момент совпадения заканчивалось. Так как оболочки могут также неверно истолковывать фигурные скобки, вы должны поместить их в апострофы, как в '{}'. В этом случае мы хотим выполнить команду cp -a '{}' /path/to/destination/dir/(-a означает архив, который повторяется в подкаталогах, копирует символические ссылки в виде ссылок и сохраняет разрешения и расширенные атрибуты и /path/to/destination/dir/, очевидно, является именем целевого каталога - замените его.)

Итак, на простом английском языке эта findкомандная строка говорит следующее:

Начните с / path / to / toplevel / dir /. Не спускайтесь ни в какие подкаталоги. Найти все каталоги, файлы и символические ссылки, чье имя начинается с точки. Для каждого из найденных объектов скопируйте его в / path / to / destination / dir / сохраняя природу, разрешения и расширенные атрибуты.

Михай Лимбашан
источник
1
найти это самая полезная вещь когда-либо.
Мистер Блестящий и Новый
1
Хороший ответ. Хотя я предпочитаю -exec ... ';' Избегание обратной косой черты означает, что эта команда будет работать как в CLI, так и в crontab :))
kubanczyk
8

Я всегда использовал. ?? *, чтобы найти скрытые файлы, не получая "." и "..". Это может пропустить ".a" или что-то, хотя, но у меня никогда не было одного из них.

Пол Томблин
источник
определенно хороший и опрятный :) +1
фальстро
Я не хочу, чтобы он таинственным образом потерпел неудачу, если есть какие-то ".a"
Zifre
Мне это нравится, потому что, если вы знаете, что у вас нет скрытых файлов, состоящих из одного символа, это очень быстро набрать.
Пол Томблин
Это должен быть лучший ответ. Это должно быть поддержано наверх.
Ибн Саид