Рекурсивное копирование скрытых файлов - Linux
Есть ли простой способ рекурсивного копирования всех скрытых файлов в каталоге в другой каталог? Я хотел бы сделать резервную копию только всех файлов настроек в домашнем каталоге, а не обычных файлов. Я старался:
cp -R .* directory
но это признает .
а также ..
и рекурсивно копирует все не скрытые файлы тоже. Есть ли способ заставить cp игнорировать .
а также ..
?
6 ответов
Моим любимым ходом режиссеров вообще было:
tar cvf - . | (cd /dest/dir; tar xvf -)
который подключает текущий каталог к стандартному выводу, а затем направляет его в подоболочку, которая сначала переписывает компакт-диск в конечный каталог перед тем, как распаковать стандартный ввод. Простой, прямой, расширяемый - подумайте, что происходит, когда вы заменяете () ssh на другой компьютер. Или, чтобы ответить на ваш вопрос, вы можете сделать:
tar cvf - .* --exclude=\. --exclude=\.\. | (cd /dest/dir; tar xvf -)
Почти каждый раз, когда это можно решить просто с помощью:
cp -R .[a-zA-Z0-9]* directory
Довольно необычно иметь скрытый файл, который не начинается с одного из этих символов.
Другие образцы соответствия доступны (.??*
, .[^.]*
) - посмотреть комментарии
Вы могли бы использовать rsync
,
rsync -a ./ /some/other/directory/
который скопирует содержимое текущего каталога (включая точечные файлы, но не включая ..
)
I implore you, step away from plain shell expansion on the cp
command line - shell expansion has all sorts of ahem "interesting" corner cases (unwanted recursion caused by. and.., spaces, non-printable stuff, hardlinks, symbolic links, and so on.) Use find
instead (it comes in the findutils
package, in case you don't have it installed - which would be weird, all distributions install it by default):
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/ \;
Step by step explanation:
-H
вызоветfind
not to follow symlinks (except if the actual toplevel directory name you gave it is a symlink; that it will follow.)/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