Skopiuj każdy plik w strukturze katalogów do określonej ścieżki tylko wtedy, gdy plik już tam nie istnieje

8

Chciałbym skopiować każdy plik ze struktury katalogów do określonego katalogu tylko wtedy, gdy plik już tam nie istnieje.

Dostałem pierwszą część z tego pytania dotyczącego przepełnienia stosu :

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

Jak mogę sprawdzić, czy plik istnieje, czy nie? Jeśli nie, skopiuj plik, w przeciwnym razie pomiń.

pan au
źródło
Czy masz na myśli „skopiuj wszystkie pliki z drzewa źródłowego do (określonego) pojedynczego katalogu bez podkatalogów”? Lub „skopiuj wszystkie pliki z drzewa źródłowego do podkatalogu katalogu docelowego, podobnie jak w drzewie źródłowym”? Przeczytałem pytanie jako pierwszy przypadek - czy możesz edytować pytanie, aby wyjaśnić? (Wiem, że masz swoją odpowiedź, ale zostanie ona przeczytana i wykorzystana przez innych.)
Volker Siegel,

Odpowiedzi:

13

Możesz użyć -uprzełącznika z cppolecenia:

kopiuj tylko wtedy, gdy plik SOURCE jest nowszy niż plik docelowy lub gdy brakuje pliku docelowego

lub użyj rsyncpolecenia z --ignore-existing:

pomiń aktualizację plików, które istnieją w odbiorniku

Przykład:

rsync --ignore-existing source/* destination/
Ravexina
źródło
3

Oryginalne polecenie można przepisać jako:

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

Kluczem jest to, że wywołujemy powłokę za pomocą określonych poleceń i przekazujemy znaleziony plik jako $1argument. Jeśli się test -e /target-directory/"$1"nie powiedzie, oznacza to, że plik nie istnieje, w którym to przypadku cpplik zostanie skopiowany.

Zasadniczo można używać innych poleceń, o ile polecenie może zweryfikować istnienie pliku. Niektóre inne alternatywy:

  • /usr/bin/realpath -e /target-directory/"$1" > /dev/null || cp "$1" /target-directory
  • stat >/dev/null /target-directory/"$1" || cp "$1" /target-directory/"$1"
Sergiy Kolodyazhnyy
źródło
2
Dlaczego warto stattestować istnienie pliku w Bash? Czy nie test -ebyłoby o wiele prostsze?
David Foerster,
@DavidFoerster Bez konkretnego powodu. polecenie testowe też zrobi. Zmienię swoją odpowiedź później, jeśli nie zapomnę
Sergiy Kolodyazhnyy,
0

Przeczytaj man cpi użyj --no-clobberopcji do cp.

waltinator
źródło