14

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

Я предполагаю, что найду необходимость исключить несколько типов файлов в ближайшем будущем. Например, я могу захотеть исключить .svn, * .bak и * .prj.

Вот то, что я собрал так для, но это не работает для меня. Первая часть, найди работы, но я делаю что-то не так с xargs и cp. Я пробовал cp с и без -R . Кроме того, я использую OS X, и у нее, похоже, менее функциональная версия xargs, чем в системах Linux.

find ./sourcedirectory -not \( -name .svn -a -prune \)
     | xargs -IFILES cp -R FILES ./destinationdirectory

9 ответов9

22

(Отредактировано после перечитывания вопроса. Спрашивающий говорит, что rsync не установлен)

Возможная проблема с вашим решением find/xargs - пробелы в именах файлов. Чтобы обойти это, скажите find и xargs использовать нулевой символ (ASCII 0) для разделения найденных файлов:

find ./sourcedirectory -not ( -name .svn -a -prune ) -print0 | xargs -0 -IFILES cp FILES ./destinationdirectory

Если вы обнаружите, что rsync доступен, я все же думаю, что rsync - гораздо лучшее решение:

Используйте rsync с опцией -C. Со страницы руководства rsync:

Это полезное сокращение для исключения широкого диапазона файлов, которые вы часто не хотите передавать между системами. Он использует алгоритм, аналогичный CVS, чтобы определить, следует ли игнорировать файл.

Это скажет rsync игнорировать эти шаблоны:

RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state .nse_depinfo *~
#* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej .del-* *.a *.olb *.o *.obj 
*.so *.exe *.Z *.elc *.ln core .svn/ .git/ .bzr/

Например:

rsync -avC /path/to/source/directory /path/to/destination/directory

(примечание: если вы еще не слишком знакомы с rsync, обязательно прочитайте на этой странице руководства о том, как rsync справляется с косой чертой в исходном пути. Он ведет себя иначе, если вы включаете косую черту, чем если вы этого не сделаете. Поиск "косая черта")

2

Грязный, но быстрый и лаконичный способ:

cp -r source destination
find destination -iname .svn |xargs rm -rf

Это копирует один каталог в другой (таким образом, рекурсивный параметр -r), а затем рекурсивно уничтожает все с именем .svn (игнорируя регистр).

2

Не общие решения, но ... вы можете использовать команду svn export для создания копии рабочей области без папок метаданных .svn.

2
%> mkdir -p FOLDER_OUT && ( tar cf - FOLDER_OR_FILES_IN --exclude=.svn  | tar xvf - -C FOLDER_OUT )

если вы хотите, вы можете даже поместить 'pv' или что-то подобное между процессами 2 tar.

1

Я бы пошел по-другому, используя tar и механизм исключения.

От в каталоге назначения:

tar -X excludefile -C source -f - . | tar xf -

Это перейдет к исходному тексту, сохранит содержимое, исключая то, что указано в excludefile, а затем распакует его в текущий каталог.

0

Вы также можете сделать наоборот. Скопируйте все, затем удалите папки .svn, используя следующую команду:

find . | grep ".svn" | xargs rm -rf
0

Не забудьте grep -v

find . | grep -v .svn
0

Отредактированный ответ: проблема в том, что -R делает ваше копирование рекурсивным, и в итоге вы копируете скрытые файлы. Вот что я бы использовал:

find source/  -mindepth 1 -not \( -name .svn -prune \) | xargs -Iitem cp item target/

Флаг -mindepth 1 указывает find игнорировать каталог верхнего уровня. Поскольку вы хотите скопировать все содержимое этого каталога в новый каталог верхнего уровня, я предполагаю, что вы этого не хотите.

Как говорит Крис Нава в своем ответе, уже есть встроенный способ сделать это, если мы говорим о папках SVN, но, поскольку вы попросили более общее решение, это может немного помочь.

0

Я полагаю, это зависит от того, насколько велико ваше дерево, но почему бы просто не скопировать все сначала, а затем обрезать папки .svn после:

find /dest-dir -type d -name .svn -exec rm -rf {} \;

?

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .