BASH скопируйте все файлы, кроме одного

111

Я хотел бы скопировать все файлы из каталога, кроме одного с именем Default.png. Кажется, есть несколько способов сделать это. Что кажется вам наиболее эффективным?

Джо Каннатти
источник
Почему вам нужно пропустить этот файл, а не просто удалить его после копирования? Он уже существует в целевом каталоге?
Лассе В. Карлсен,
1
Да, файл с таким именем уже существует в целевом каталоге.
Джо Каннатти
@ LasseV.Karlsen: Или вы можете сэкономить время на его копирование, если это большой файл. Меня это интересует, но за исключением каталога, а не файла.
Nikana Reklawyks

Ответы:

55

Просто, если src/содержит только файлы:

find src/ ! -name Default.png -exec cp -t dest/ {} +

Если src/есть подкаталоги, он их пропускает, но копирует файлы внутри них:

find src/ -type f ! -name Default.png -exec cp -t dest/ {} +

Если src/есть подкаталоги, это не рекурсивно в них:

find src/ -type f -maxdepth 1 ! -name Default.png -exec cp -t dest/ {} +
Джон Кугельман
источник
5
Это оказалось для меня лучшим вариантом, потому что, похоже, OS X поставляется без включенного glob.
Джо Каннатти
6
@Max \;выполняет команду один раз для каждого файла. +выполняет команду один раз и сразу передает ей все имена файлов (в соответствии с ограничением длины командной строки). +в целом немного более эффективен.
Джон Кугельман
149

Должно быть следующее:

cp -r !(Default.png) /dest

При копировании в папку, вложенную в текущую папку (в приведенном ниже примере это называется примером), вам также необходимо пропустить этот каталог:

cp -r !(Default.png|example) /example
Джон
источник
17
Это дает -bash:!: Событие не найдено
Джо Каннатти
Вы копируете файлы в папку, вложенную в папку, из которой вы копируете?
Джон
47
Это необходимо shopt -s extglobдля работы, если она была отключена.
Барри Келли
5
Кажется, что OS X нужно использовать, shopt -s extglobкак описано @BarryKelly. С этим все работает отлично.
Кэт
Годы на Баше и не знали о !()... Красиво! Для тех, кто - как и я - считает, что пришло время изучить / просмотреть bash , вот соответствующие ссылки, связанные с этим вопросом / ответом: shopt / extglob и шаблон .
Brandt
73

rsync долгое время был моей заменой cp / scp:

rsync -av from/ to/ --exclude=Default.png

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
-v, --verbose               increase verbosity
Матья
источник
Если я хочу исключить два разных файла, как мне это использовать?
Pulkit Bansal
поддерживаются несколько аргументов --exclude =. И не забывайте -rаргумент, если вы синхронизируете каталоги
Риан Сандерсон
5

Я бы просто сделал:

cp srcdir/* destdir/ ; rm destdir/Default.png

если файлы не большие. В противном случае используйте, например,

find srcdir -type f/ |grep -v Default.png$ |xargs -ILIST cp LIST destdir/
нет
источник
1
Первая команда - это не то, о чем просил OP. Если он Default.pngсуществует в двух каталогах, он заменит один в destdirдругом srcdir, а затем удалит скопированный Default.png. Вместо этого OP хочет сохранить то, Default.pngчто уже существует в destdir.
SnowFrog
2
как насчет того, что default.png уже существует в destdir? Ваше решение не сработает.
Иман Мохамади 03
2

Это отлично подходит для копирования всего, кроме узловых модулей :) наслаждайтесь, и благодаря приведенным выше ответам я только что добавил к нему. На мой взгляд, Rsync лучше, чем CP, так как вы можете видеть индикатор выполнения, даже не спрашивая об этом.

   rsync -av fromDirectory/ ToDirectory/ --exclude=node_modules
Джош
источник
0
cp `ls | grep -v Default.png` destdir
Уилл Хартунг
источник
5
Это с большей вероятностью приведет к ошибкам, чем то, что вы намереваетесь.
Приостановлено до дальнейшего уведомления.
-1
# chattr +i /files_to_exclude
# cp source destination
# chattr -i /files_to_exclude
Иван Гриненко
источник
-2

используйте параметр расширения оболочки с регулярным выражением

cp /<path>/[^not_to_copy_file]* .

Будет скопировано все, кроме not_to_copy_file

- если с этим что-то не так. пожалуйста уточни !

Алекс
источник
1
Добро пожаловать в SO. К сожалению, ваш ответ неверен. Выражение в квадратных скобках ( [...]) содержит набор символов для сопоставления, в то время как начало ^приведет к совпадению дополнения перечисленных символов. В следующем примере, ни файл будет в списке: touch not_to_copy_file to_copy_file ; ls [^not_to_copy_file]*потому что все имена файлов , начинающиеся с любым из следующих символов будут исключены: _cefilnopty.
rtx13