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

8

Хотел бы скопировать каждый файл из структуры каталогов в конкретный каталог, только если файл там еще не существует.

Получил первую часть из этого вопроса переполнения стека :

find . -type f -exec cp {} /target-directory \;

Как я могу проверить, существует ли файл или нет? Если нет, скопируйте файл, иначе пропустите.

мистер ау
источник
Вы имеете в виду «скопировать все файлы в дереве исходных текстов в (определенный) отдельный каталог без подкаталогов»? Или «скопировать все файлы в исходном дереве в подкаталог целевого каталога, аналогичный тому, где он был в исходном дереве»? Я прочитал вопрос в качестве первого случая - вы можете отредактировать вопрос, чтобы уточнить? (Я знаю, что у вас есть свой ответ, но он будет прочитан и использован другими.)
Volker Siegel

Ответы:

13

Вы можете использовать -uпереключатель из cpкоманды:

копировать только в том случае, если файл SOURCE новее, чем файл назначения, или когда файл назначения отсутствует

или используйте rsyncкоманду с --ignore-existing:

пропустить обновление файлов, которые существуют на приемнике

Пример:

rsync --ignore-existing source/* destination/
Ravexina
источник
3

Ваша оригинальная команда может быть переписана как:

find . -type f -exec bash -c 'test -e /target-directory/"$1" || cp "$1" /target-directory' sh {} \;

Ключевым моментом здесь является то, что мы вызываем shell с конкретными командами и передаем найденный файл в качестве $1аргумента. Если происходит test -e /target-directory/"$1"сбой, это означает, что файл не существует, и в этом случае cpбудет скопировать файл.

В общем, можно использовать другие команды, если команда может проверить существование файла. Некоторые из других альтернатив:

  • /usr/bin/realpath -e /target-directory/"$1" > /dev/null || cp "$1" /target-directory
  • stat >/dev/null /target-directory/"$1" || cp "$1" /target-directory/"$1"
Сергей Колодяжный
источник
2
Зачем statпроверять наличие файлов в Bash? Не было test -eбы намного проще?
Дэвид Фёрстер
@DavidFoerster Никакой конкретной причины. Тестовая команда тоже подойдет. Я отредактирую свой ответ позже, если не забуду
Сергей Колодяжный
0

Прочитайте man cpи используйте --no-clobberопцию для cp.

waltinator
источник