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

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

Ответ 1

rsync быстрый и простой:

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

Ответ 2

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

bash

Ссылка в руководство, найдите 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), для регулярных выражений со звездами и классами символов. Подробнее см. В man-странице.

ЗШ

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

Вы можете сделать 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. Еще раз, для получения полной информации обратитесь к manpage.


Бонус-подсказка

Введите cp *, нажмите Ctrl X * и просто посмотрите, что произойдет. это не вредно Я обещаю

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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

Ответ 6

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

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

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

Ответ 7

Развернувшись на комментарий mvdss, это работает для меня

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

Ответ 8

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

Ответ 9

Rsync

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

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

Ответ 10

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

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

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

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

Ответ 11

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

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

Ответ 15

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

    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 $'\0' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done

Я использую приведенное выше, чтобы скопировать все файлы музыкального типа, которые являются более новыми на моем сервере, чем файлы в живом концентраторе Western Digital TV Live, который я установил на /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/