Есть ли простой способ рекурсивно скопировать все скрытые файлы из каталога в другой каталог? Я хотел бы создать резервную копию только всех файлов настроек в домашнем каталоге, а не обычных файлов. Я попытался:
cp -R .* directory
но он признает .
и ..
а также рекурсивно копирует все не скрытые файлы. Есть ли способ заставить cp игнорировать .
и ..
?
Практически каждый раз это можно решить с помощью:
cp -R .[a-zA-Z0-9]* directory
Довольно необычно иметь скрытый файл, который не начинается с одного из этих символов.
Доступны другие совпадения с образцом (.??*
, .[^.]*
) - см. комментарии
Моим любимым способом перемещения каталогов в целом было:
tar cvf - . | (cd /dest/dir; tar xvf -)
который преобразует текущий каталог в стандартный вывод, а затем направляет его в подоболочку, которая сначала выполняет компакт-диск в целевой каталог перед распаковкой stdin. Простой, прямой, расширяемый - подумайте, что произойдет, если вы замените () на ssh на другой машине. Или, чтобы ответить на ваш вопрос, вы можете сделать:
tar cvf - .* --exclude=\. --exclude=\.\. | (cd /dest/dir; tar xvf -)
Вы могли бы использовать rsync
.
rsync -a ./ /some/other/directory/
который скопирует содержимое текущего каталога (включая точечные файлы, но не включая ..
)
Умоляю вас, отойдите от простого расширения оболочки на 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 / с сохранением характера, разрешений и расширенных атрибутов.
Я всегда использовал. ?? *, чтобы найти скрытые файлы, не получая "." и "..". Хотя он может пропустить ".a" или что-то в этом роде, но у меня их никогда не было.
Здесь гораздо лучшие ответы; https://superuser.com/questions/61611/how-to-copy-with-cp-to-include-hidden-files-and-hidden-directories-and-their-con
Он описывает, например, использование shopt для нативного решения bash.