Как использовать команду " cp " для исключения определенного каталога?

Я хочу скопировать все файлы в каталог, кроме некоторых файлов в определенном подкаталоге. Я заметил, что команда " cp " не имела опции --exclude. Итак, как я могу достичь этого?

17 ответов


rsync быстро и легко:

rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude

можно использовать --exclude кратно раз.

также вы можете добавить -n для сухого запуска, чтобы увидеть, что будет скопировано перед выполнением реальной операции, и если все в порядке, удалите -n из командной строки.


Ну, если исключение определенных шаблонов файлов должно было выполняться каждой утилитой файлов unix-ish (например, cp, mv, rm, tar, rsync, scp,...), произойдет огромное дублирование усилий. Вместо этого, такие вещи могут быть сделаны как часть подстановка, то есть вашей оболочкой.

Баш

ссылке в ручную, поиск extglob.

пример:

$ shopt -s extglob
$ echo images/*
images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png
$ echo images/!(*.jpg)
images/004.bmp images/2252.png

так что вы просто поместите шаблон внутри !(), и это отрицает совпадение. Шаблон может быть сколь угодно сложным, начиная с перечисления отдельных путей (как показывает Ванварил в другом ответе):!(filename1|path2|etc3), чтобы regex-подобные вещи со звездами и классами символов. См. manpage для деталей.

ЗШ

ссылке в руководстве, раздел "генерация имени файла".

можно сделать setopt KSH_GLOB и используйте bash-подобные шаблоны. Или,

% setopt EXTENDED_GLOB
% echo images/*
images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png
% echo images/*~*.jpg
images/004.bmp images/2252.png

так x~y соответствует шаблону x, но исключающий шаблон y. Еще раз, для полной информации обратитесь к странице помощи.


рыбноеновый!

на рыбное shell имеет гораздо красивее ответ для этого:

 cp (string match -v '*.excluded.names' -- srcdir/*) destdir

бонус pro-tip

тип cp *, нажмите CtrlX* и просто посмотреть, что происходит. это не вредно обещаю


зачем использовать rsync когда вы можете сделать:

find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'

предполагается, что целевая структура каталогов совпадает с исходной.


cp -r `ls -A | grep -v "c"` $HOME/

самый простой способ, который я нашел, где вы можете скопировать все файлы, исключая файлы и папки, просто добавив их имена в скобках:

cp -r !(Filename1 | FoldernameX | Filename2) Dest/

Я предполагаю, что вы используете bash или dash. Сработает ли это?

shopt -s extglob  # sets extended pattern matching options in the bash shell
cp $(ls -laR !(subdir/file1|file2|subdir2/file3)) destination

выполнение ls, исключая файлы, которые вы не хотите, и используя это в качестве первого аргумента для cp


расширения комментарий mvds, это работает для меня

cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2

другой более простой вариант-установить и использовать rsync, который имеет параметр --exclude-dir и может использоваться как для локальных, так и для удаленных файлов.


rsync

rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/

и сначала попробуйте с опцией-n, чтобы увидеть, что будет скопировано


Это модификация ответа Лайнуса Клина. Его ответ не сработал для меня, потому что был бы . добавлен перед путем файла, который не нравится cp (путь будет выглядеть как source/.файл назначения.)

эта команда сработала для меня:

find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;

команда --parents сохраняет структуру каталогов.


это относительно исходного каталога.
Это исключит каталог source/.git копировать.

rsync -r --exclude '.git' source target

mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/

просто переместите его временно в скрытый каталог (и переименуйте его после, если хотите).

mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname

один из способов-использовать find -0 с -prune найти все файлы и каталоги, которые вы хотите переместить, а затем использовать xargs -0 скопировать каждый.


cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir

Edit: забыл исключить целевой путь (в противном случае он будет рекурсивно копировать).


Я использую цикл "do while" для чтения вывода команды find. В этом примере я сопоставляю (а не исключаю) определенные шаблоны, поскольку есть более ограниченное количество совпадений шаблонов, которые я хочу, чем то, что я не хочу. Вы можете изменить логику с помощью a-not перед флагами-iname:

    find . -type f -iname "*.flac" -o -print0 -iname "*.mp3" -print0 -o -iname "*.wav" -print0 -o -iname "*.aac" -print0 -o -iname "*.wma" -print0 | while read -d $'' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done

Я использую выше, чтобы скопировать все файлы типа музыки, которые новее на моем сервере, чем файлы на Western Digital TV Live Hub, который я установил в /media / wd. Я использую выше, потому что у меня много DVD-файлов, MPEG и т. д. это я хочу исключить и потому, что по какой-то причине rsync выглядит как копирование, но после того, как я смотрю на устройство wd, файлов нет, несмотря на отсутствие ошибок во время rsync с этой командой:

    rsync -av --progress --exclude=*.VOB --exclude=*.avi --exclude=*.mkv --exclude=*.ts --exclude=*.mpg --exclude=*.iso --exclude=*ar --exclude=*.vob --exclude=*.BUP --exclude=*.cdi --exclude=*.ISO --exclude=*.shn --exclude=*.MPG --exclude=*.AVI --exclude=*.DAT --exclude=*.img --exclude=*.nrg --exclude=*.cdr --exclude=*.bin --exclude=*.MOV --exclude=*.goutputs* --exclude=*.flv --exclude=*.mov --exclude=*.m2ts --exclude=*.cdg --exclude=*.IFO --exclude=*.asf --exclude=*.ite /media/2TB\ Data/data/music/* /media/wd/network_sync/music/

rsync на самом деле довольно сложно. нужно сделать несколько тестов, чтобы это сработало.

Допустим, вы хотите скопировать /var/www/html to /var/www/dev а нужно исключить /var/www/html/site/video/ каталог, возможно, из-за его размера. Команда будет:

rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev

некоторые предостережение:

  1. последняя черта / в источнике необходимо, в противном случае он также скопирует исходный каталог, а не его содержимое и становится /var/www/dev/html/xxxx, что, возможно, не то, что вы хотите.
  2. the --exclude путь относительные непосредственно к источнику. Даже если вы поставите полный абсолютный путь, это не сработает.

  3. -v для подробного, -a для режима архива, что означает, что вы хотите рекурсия и хотят сохранить почти все.