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

411

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

Дэвид Лю
источник
18
Rsync?
ajreal
6
tar -c | tar -x?
MVDS
1
@mvds, согласен с вами, использование tar с '--exclude' - хорошая идея.
Хуан Ф. Лей

Ответы:

705

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

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

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

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

Обратите внимание , что реж thefoldertoexcludeпосле --excludeопции относительно к sourcefolder, т sourcefolder/thefoldertoexclude.

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

моток
источник
3
Согласитесь, вы не можете победить простоту и мощь--exclude
Мэтью Уилкоксон
31
это thefoldertoexcludeотносительный sourcefolderили текущий рабочий каталог? спасибо
Beebee
46
Это относительно исходной папки. Это исключит возможность копирования папки source / .git. rsync -r --exclude '.git' source target
orkoden
15
Может быть, я ошибаюсь, но я считаю хорошей практикой добавлять «переключатели» перед «параметрами». Также man-страница отчетов rsync - исключает возможность использования как с синтаксисом "=", так и без него. Поэтому, чтобы стандартизировать операционные системы, я бы использовал rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder- в любом случае upvote для rsync вместо find, поскольку вы можете легко использовать абсолютные пути для источника, а в find это сложнее, чем {}в dst.
Хави Монтеро
1
@mamun Конечно, например, с удаленного сервера на локальный компьютер: $ rsync user@example.com:/var/www/mypage /var/www/mylocalpage/или с локального на удаленный$ rsync /var/www/mylocalpage/ user@example.com:/var/www/mypage
sobi3ch
84

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

удар

man 1 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 1 zshexpn, / генерация имени файла .

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


рыба новая!

У раковины рыбы есть намного более симпатичный ответ на это:

🐟 cp (строка соответствует -v '* .excluded.names' - srcdir / *) destdir

Бонус pro-tip

Набери cp *, нажми CtrlX*и посмотри что получится. это не вредно, я обещаю

ulidtko
источник
@MikhailGolubtsov, возможно, это потому, что глобализация не является рекурсивной и работает по одному уровню за раз. Отредактировано. PS: это работает, zshхотя.
ulidtko
3
Хороший pro-tip! Таким образом, вы можете легко удалить отдельные элементы. Большое спасибо!
Таффит
Кстати, чтобы отключить расширенные функции сопоставления с образцом в Bash, запустите setopt -u extglob.
Rockallite
49

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

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

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

Линус Клин
источник
8
Я думаю, что вам нужен -pathаргумент для проверки иерархии путей, а не
Джеймс
3
И вам также понадобится точка с запятой в конце:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Мэтью Уилкоксон
1
Ничего себе, это не позволит мне: "Правки должны быть не менее 6 символов"!
Мэтью Уилкоксон
1
@MatthewWilcoxson Meh. Эти ограничения будут сняты, как только вы получите немного больше повторений. Я отредактировал ответ соответственно. Еще раз спасибо!
Линус Клин
1
@ Хеннинг, почему бы и нет rsync? Ведь это может отсутствовать в системе! в то время как find, cpвсегда на своих местах. Или вы из тех парней, которые установили 2 гига штуки, чтобы делать простые вещи?
Рейшин
37
cp -r `ls -A | grep -v "c"` $HOME/
винет кумар
источник
1
Работал для меня в Windows 10 .sh
atwellpub
Сделана функция оболочки, которая упрощает использование пользовательского исходного пути и # $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
исключает
не удается с каталогами с пробелами
Сержио
27

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

shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
securecurve
источник
9
Не работает для меня Я получаю-bash: !: event not found
Geneorama
8
shopt -s extglob (выполните это, чтобы включить! в cp, rm и других)
imkost
10

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

rsync -r --exclude '.git' source target
Нияз Ахмед Куреши
источник
В чем разница / улучшение по сравнению с лучшим ответом?
снижение активности
8

Rsync

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

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

dzon
источник
В чем разница / улучшение по сравнению с лучшим ответом?
снижение активности
7

Я предполагаю, что вы используете 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

Vanwaril
источник
9
Вы можете пропустить лишнее lsи просто сделать cp !(file1|file1) dest.
Шон Чин
Не используйте -laR. это добавляет строку, которая мешает cp. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL
5

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

ehudokai
источник
4

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

Допустим, вы хотите скопировать /var/www/htmlв /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. --excludeПуть по отношению к источнику непосредственно. Даже если вы поставите полный абсолютный путь, он не будет работать.

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

Леон - Хан Ли
источник
простое решение, которое заботится о специальных символах и
Сержио
Спасибо за объяснение параметров, в отличие от текущего топ ответа!
снижение активности
3
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir

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

работа sudo
источник
4
Не упустите записи каталога, содержащие пробелы.
Пауло Скардин
3

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

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

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

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

Милан Симек
источник
2
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
Джон Смит
источник
2

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

mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
lama12345
источник
1
Возможно, не очень - но это единственный вариант, который я здесь нашел, который работает со cpстандартной оболочкой POSIX sh.
Томекви
1
Этот ответ резко недооценен. Это самый совместимый, самый легкий для чтения и легкий для понимания ответ. Престижность, я не знаю, почему я не думал об этом.
Роберт Талада
Спасибо @RobertTalada, как далеко зайдет ответ? ️‍🌈
lama12345
0

Я использую цикл "do while", чтобы прочитать вывод команды find. В этом примере я сопоставляю (а не исключаю) определенные шаблоны, так как есть более ограниченное число сопоставлений с образцами, которые я хочу, чем те, которые я не хочу. Вы можете изменить логику с -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 $'\0' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done

Я использую вышеупомянутое, чтобы скопировать все файлы музыкального типа, которые являются более новыми на моем сервере, чем файлы на Live Digital Hub Western Digital TV, которые я смонтировал в / media / wd. Я использую вышеупомянутое, потому что у меня есть много файлов DVD, mpegs и т. Д., Которые я хочу исключить И, потому что по какой-то причине 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/
user3610268
источник
0
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir 

Первая часть lsвсех файлов, но скрытые конкретные файлы с флагом -I. Вывод lsиспользуется как стандартный ввод для второй части. xargsпостроить и выполнить команду cp -rf -t destdirиз стандартного ввода. флаг -rозначает рекурсивное копирование каталогов, -fозначает принудительное копирование файлов, которые будут перезаписывать файлы в destdir, -tуказывать конечный каталог для копирования.

LouisXW
источник
0

cp -r ls -A | grep -v "Excluded_File_or_folder"../$target_location -v

Шашвот Рисал
источник