Як використовувати команду 'cp' для виключення конкретного каталогу?


411

Я хочу скопіювати всі файли в каталог, крім деяких файлів у певний підкаталог. Я помітив, що команда 'cp' не мала опції --exclude. Отже, як я можу цього досягти?



6
tar -c | tar -x?
mvds

1
@mvds, погоджуюсь із вами, використання tar з позначкою "--exclude" - хороша ідея.
Хуан Ф. Лей

Відповіді:


703

rsync - це швидко і легко:

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

Ви можете використовувати --excludeкратні рази.

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

Зауважте, що варіант dir thefoldertoexcludeafter --excludeє відносном sourcefolder, тобто sourcefolder/thefoldertoexclude.

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


3
Домовились, ви не можете перемогти простоту і силу--exclude
Меттью Вілкокссон

31
є thefoldertoexcludeвідносном sourcefolderчи поточним робочим режимом? дякую
Beebee

46
Це відносно папки-джерела. Це виключить джерело папки / .git з копіювання. rsync -r --exclude '.git' Вихідна ціль
orkoden

15
Можливо, я помиляюся, але я вважаю, що доречно додавати "перемикачі" перед "параметрами". Також довідкова сторінка звітів rsync - виключає корисну, як у синтаксисі "=" або без. Тому для стандартизації між операційними системами я б використовував rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder- у будь-якому випадку, підсилюйте rsync замість знахідки, оскільки ви можете легко використовувати абсолютні шляхи до джерела, тоді як у знаходженні це складніше, як це використовується {}у 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, / екстглоб .

Приклад:

$ shopt -s extglob
$ echo зображення / *
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
% ехо-зображень / *
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. Ще раз, для отримання детальної інформації див. Сторінку.


риба нова!

Риби оболонка має багато красивіше відповідь на цей питання :

🐟 cp (рядок рядків -v '* .excluded.names' - srcdir / *) destdir

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

Наберіть cp *, натисніть CtrlX*і просто подивіться, що станеться. це не шкідливо, обіцяю


@MikhailGolubtsov, можливо, тому, що глобалізація не є рекурсивною і працює один за одним. Відредаговано. PS: він працює, zshхоча.
ulidtko

3
Гарний підказки! Таким чином ви можете легко видалити окремі елементи. Дуже дякую!
таффіт

BTW, щоб вимкнути розширені функції відповідності шаблону в 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
@Henning чому б і ні 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 }
ElectRocnic

не виходить із каталогів з пробілами
Sérgio

27

Найпростіший спосіб я знайшов, куди ви можете скопіювати всі файли, крім файлів і папок, просто додавши їхні імена в круглі дужки:

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

9
Не працює для мене. Я отримую-bash: !: event not found
geneorama

8
shopt -s extglob (виконайте це, щоб увімкнути! в cp, rm та інших)
imkost



8

rsync

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

і спершу спробуйте -n, ​​щоб побачити, що буде скопійовано


У чому різниця / поліпшення порівняно з головною відповіддю?
зменшення активності

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


9
Можна пропустити зайве lsі просто зробити cp !(file1|file1) dest.
Шон Чін

Не використовуйте -лаР. до нього додається рядок, що заважає cp. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL

5

Ще один простіший варіант - встановити та використовувати rsync, який має опцію --exclude-dir, і може використовуватися як для локальних, так і для віддалених файлів.


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

Редагувати: також забув виключити цільовий шлях (інакше він буде рекурсивно копіювати).


4
стежте за записами каталогів, що містять пробіли.
Пауло Скардин

3

Це модифікація відповіді Лінуса Кліна. Його відповідь не спрацювала для мене, оскільки це було б. Додано перед файлом шлях, який не подобається cp (шлях буде схожий на source / .destination / file).

Ця команда працювала для мене:

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

команда --parents зберігає структуру каталогу.


2

Просто перемістіть її тимчасово в приховану директорію (і перейменуйте її після, якщо потрібно).

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

1
Не дуже можливо - але це єдиний варіант, який я тут знайшов, і працює cpяк стандартна оболонка POSIX sh.
tomekwi

1
Ця відповідь різко занижена. Це найбільш сумісна, найпростіша для читання і легка для розуміння відповідь. Кудо, я не знаю, чому я про це не думав.
Роберт Талада

Дякую @RobertTalada, як далеко відповідь піде відтепер? ️‍🌈
lama12345


0

Для читання результатів команди find я використовую цикл "do while". У цьому прикладі я співставляю (а не виключаю) певні шаблони, оскільки є більш обмежена кількість відповідностей шаблонів, яку я хочу, ніж те, що я не хочу. Ви можете змінити логіку за допомогою кнопки -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

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

0
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir 

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.