Как использовать команду «cp» для исключения определенного каталога?
411
Я хочу скопировать все файлы в каталоге, кроме некоторых файлов в определенном подкаталоге. Я заметил, что команда 'cp' не имеет опции --exclude. Итак, как мне этого добиться?
Обратите внимание , что реж thefoldertoexcludeпосле --excludeопции относительно к sourcefolder, т sourcefolder/thefoldertoexclude.
Также вы можете добавить -nпробный запуск, чтобы увидеть, что будет скопировано перед выполнением реальной операции, и, если все в порядке, удалить -nиз командной строки.
Согласитесь, вы не можете победить простоту и мощь--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, ...), произойдет огромное дублирование усилий. Вместо этого, такие вещи могут быть сделаны как часть подстановка , то есть с помощью вашей оболочки.
Таким образом, вы просто помещаете шаблон внутрь !(), и это сводит на нет совпадение. Шаблон может быть сколь угодно сложным, начиная от перечисления отдельных путей (как Ванварил показывает в другом ответе): !(filename1|path2|etc3)до регулярных выражений с звездами и классами персонажей. Обратитесь к странице справки для деталей.
@MikhailGolubtsov, возможно, это потому, что глобализация не является рекурсивной и работает по одному уровню за раз. Отредактировано. PS: это работает, zshхотя.
ulidtko
3
Хороший pro-tip! Таким образом, вы можете легко удалить отдельные элементы. Большое спасибо!
Таффит
Кстати, чтобы отключить расширенные функции сопоставления с образцом в Bash, запустите setopt -u extglob.
Я думаю, что вам нужен -pathаргумент для проверки иерархии путей, а не
Джеймс
3
И вам также понадобится точка с запятой в конце:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Мэтью Уилкоксон
1
Ничего себе, это не позволит мне: "Правки должны быть не менее 6 символов"!
Мэтью Уилкоксон
1
@MatthewWilcoxson Meh. Эти ограничения будут сняты, как только вы получите немного больше повторений. Я отредактировал ответ соответственно. Еще раз спасибо!
Линус Клин
1
@ Хеннинг, почему бы и нет rsync? Ведь это может отсутствовать в системе! в то время как find, cpвсегда на своих местах. Или вы из тех парней, которые установили 2 гига штуки, чтобы делать простые вещи?
Вы можете пропустить лишнее lsи просто сделать cp !(file1|file1) dest.
Шон Чин
Не используйте -laR. это добавляет строку, которая мешает cp. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL
5
Другой более простой вариант - установить и использовать rsync, который имеет опцию --exclude-dir и может использоваться как для локальных, так и для удаленных файлов.
rsyncна самом деле довольно сложно. нужно сделать несколько тестов, чтобы это работало.
Допустим, вы хотите скопировать /var/www/htmlв /var/www/devно необходимости исключить/var/www/html/site/video/ каталог , возможно , из - за его размера. Команда будет:
Последняя косая черта /в источнике необходима, иначе она также будет копировать исходный каталог, а не его содержимое, и становится/var/www/dev/html/xxxx , что, возможно, не то, что вам нужно.
--excludeПуть по отношению к источнику непосредственно. Даже если вы поставите полный абсолютный путь, он не будет работать.
-vдля подробного, -aдля режима архива, который означает, что вы хотите рекурсию и хотите сохранить почти все.
Это модификация ответа Линуса Клина. Его ответ не работает для меня, потому что будет. добавляется перед путем к файлу, который не нравится cp (путь будет выглядеть как source / .destination / file).
Возможно, не очень - но это единственный вариант, который я здесь нашел, который работает со cpстандартной оболочкой POSIX sh.
Томекви
1
Этот ответ резко недооценен. Это самый совместимый, самый легкий для чтения и легкий для понимания ответ. Престижность, я не знаю, почему я не думал об этом.
Роберт Талада
Спасибо @RobertTalada, как далеко зайдет ответ? ️🌈
lama12345
0
Я использую цикл "do while", чтобы прочитать вывод команды find. В этом примере я сопоставляю (а не исключаю) определенные шаблоны, так как есть более ограниченное число сопоставлений с образцами, которые я хочу, чем те, которые я не хочу. Вы можете изменить логику с -not перед флагами -iname:
Я использую вышеупомянутое, чтобы скопировать все файлы музыкального типа, которые являются более новыми на моем сервере, чем файлы на Live Digital Hub Western Digital TV, которые я смонтировал в / media / wd. Я использую вышеупомянутое, потому что у меня есть много файлов DVD, mpegs и т. Д., Которые я хочу исключить И, потому что по какой-то причине rsync выглядит так, как будто он копирует, но после того, как я посмотрел на устройство wd, файлов там нет, несмотря на отсутствие ошибки во время rsync с этой командой:
Первая часть lsвсех файлов, но скрытые конкретные файлы с флагом -I. Вывод lsиспользуется как стандартный ввод для второй части. xargsпостроить и выполнить команду cp -rf -t destdirиз стандартного ввода. флаг -rозначает рекурсивное копирование каталогов, -fозначает принудительное копирование файлов, которые будут перезаписывать файлы в destdir, -tуказывать конечный каталог для копирования.
tar -c | tar -x
?Ответы:
rsync быстр и прост:
Вы можете использовать
--exclude
кратные разы.Обратите внимание , что реж
thefoldertoexclude
после--exclude
опции относительно кsourcefolder
, тsourcefolder/thefoldertoexclude
.Также вы можете добавить
-n
пробный запуск, чтобы увидеть, что будет скопировано перед выполнением реальной операции, и, если все в порядке, удалить-n
из командной строки.источник
--exclude
thefoldertoexclude
относительныйsourcefolder
или текущий рабочий каталог? спасибоrsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
- в любом случае upvote для rsync вместо find, поскольку вы можете легко использовать абсолютные пути для источника, а в find это сложнее, чем{}
в dst.$ rsync user@example.com:/var/www/mypage /var/www/mylocalpage/
или с локального на удаленный$ rsync /var/www/mylocalpage/ user@example.com:/var/www/mypage
Что ж, если исключение определенных шаблонов имен файлов должно выполняться каждой файловой утилитой unix-ish (например, cp, mv, rm, tar, rsync, scp, ...), произойдет огромное дублирование усилий. Вместо этого, такие вещи могут быть сделаны как часть подстановка , то есть с помощью вашей оболочки.
удар
man 1 bash
, / extglob .Пример:
Таким образом, вы просто помещаете шаблон внутрь
!()
, и это сводит на нет совпадение. Шаблон может быть сколь угодно сложным, начиная от перечисления отдельных путей (как Ванварил показывает в другом ответе):!(filename1|path2|etc3)
до регулярных выражений с звездами и классами персонажей. Обратитесь к странице справки для деталей.ЗШ
man 1 zshexpn
, / генерация имени файла .Вы можете делать
setopt KSH_GLOB
и использовать шаблоны, похожие на bash. Или,Так
x~y
соответствует шаблонуx
, но исключает шаблонy
. Еще раз, для полной информации обратитесь к странице man.рыба новая!
У раковины рыбы есть намного более симпатичный ответ на это:
Бонус pro-tip
Набери
cp *
, нажми CtrlX*и посмотри что получится. это не вредно, я обещаюисточник
zsh
хотя.setopt -u extglob
.Зачем использовать,
rsync
когда вы можете сделать:Это предполагает, что структура целевого каталога совпадает с исходной структурой.
источник
-path
аргумент для проверки иерархии путей, а неfind . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
? Ведь это может отсутствовать в системе! в то время какfind
,cp
всегда на своих местах. Или вы из тех парней, которые установили 2 гига штуки, чтобы делать простые вещи?источник
# $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 }
Я нашел самый простой способ, где вы можете скопировать все файлы, кроме файлов и папок, просто добавив их имена в скобках:
источник
-bash: !: event not found
Расширяя комментарий mvds , это работает для меня
источник
Это относительно исходного каталога.
Это исключит
source/.git
копирование каталога .источник
Rsync
и сначала попробуйте это с опцией -n, чтобы увидеть, что будет скопировано
источник
Я предполагаю, что вы используете Bash или Dash. Будет ли это работать?
Выполнение ls, исключая ненужные файлы, и использование этого в качестве первого аргумента для cp
источник
ls
и просто сделатьcp !(file1|file1) dest
.cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
Другой более простой вариант - установить и использовать rsync, который имеет опцию --exclude-dir и может использоваться как для локальных, так и для удаленных файлов.
источник
rsync
на самом деле довольно сложно. нужно сделать несколько тестов, чтобы это работало.Допустим, вы хотите скопировать
/var/www/html
в/var/www/dev
но необходимости исключить/var/www/html/site/video/
каталог , возможно , из - за его размера. Команда будет:rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev
Некоторые оговорки :
/
в источнике необходима, иначе она также будет копировать исходный каталог, а не его содержимое, и становится/var/www/dev/html/xxxx
, что, возможно, не то, что вам нужно.--exclude
Путь по отношению к источнику непосредственно. Даже если вы поставите полный абсолютный путь, он не будет работать.-v
для подробного,-a
для режима архива, который означает, что вы хотите рекурсию и хотите сохранить почти все.источник
Изменить: забыл исключить целевой путь, а также (в противном случае он будет копировать рекурсивно).
источник
Это модификация ответа Линуса Клина. Его ответ не работает для меня, потому что будет. добавляется перед путем к файлу, который не нравится cp (путь будет выглядеть как source / .destination / file).
Эта команда работала для меня:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
Команда --parents сохраняет структуру каталогов.
источник
источник
Просто переместите его временно в скрытый каталог (и переименуйте его после, если хотите).
источник
cp
стандартной оболочкой POSIXsh
.Я использую цикл "do while", чтобы прочитать вывод команды find. В этом примере я сопоставляю (а не исключаю) определенные шаблоны, так как есть более ограниченное число сопоставлений с образцами, которые я хочу, чем те, которые я не хочу. Вы можете изменить логику с -not перед флагами -iname:
Я использую вышеупомянутое, чтобы скопировать все файлы музыкального типа, которые являются более новыми на моем сервере, чем файлы на Live Digital Hub Western Digital TV, которые я смонтировал в / media / wd. Я использую вышеупомянутое, потому что у меня есть много файлов DVD, mpegs и т. Д., Которые я хочу исключить И, потому что по какой-то причине rsync выглядит так, как будто он копирует, но после того, как я посмотрел на устройство wd, файлов там нет, несмотря на отсутствие ошибки во время rsync с этой командой:
источник
Первая часть
ls
всех файлов, но скрытые конкретные файлы с флагом-I
. Выводls
используется как стандартный ввод для второй части.xargs
построить и выполнить командуcp -rf -t destdir
из стандартного ввода. флаг-r
означает рекурсивное копирование каталогов,-f
означает принудительное копирование файлов, которые будут перезаписывать файлы вdestdir
,-t
указывать конечный каталог для копирования.источник
cp -r
ls -A | grep -v "Excluded_File_or_folder"
../$target_location -vисточник