Polecenie cp: poprawne kopiowanie folderów plików w *nix

Polecenie cp: poprawne kopiowanie folderów plików w *nix

W tym artykule ujawnimy kilka nieoczywistych rzeczy związanych z użytkowaniem symbole wieloznaczne podczas kopiowania, niejednoznaczne zachowanie poleceń cp podczas kopiowania, a także metody, które pozwalają poprawnie skopiować ogromną liczbę plików bez pomijania lub awarii.

Powiedzmy, że musimy skopiować wszystko z folderu /source do folderu /target.

Pierwszą rzeczą, która przychodzi na myśl jest:

cp /source/* /target

Natychmiast poprawmy to polecenie na:

cp -a /source/* /target

klucz -a doda kopiowanie wszystkich atrybutów, praw i doda rekurencję. Gdy nie jest wymagane dokładne odwzorowanie praw, wystarczy klucz -r.

Po skopiowaniu okaże się, że nie wszystkie pliki zostały skopiowane - pliki zaczynające się od kropki np.:

.profile
.local
.mc

i tym podobne.

Dlaczego się to stało?

Ponieważ symbole wieloznaczne są przetwarzane przez powłokę (bash w typowym przypadku). Domyślnie bash ignoruje wszystkie pliki zaczynające się od kropek, ponieważ traktuje je jako ukryte. Aby uniknąć takiego zachowania, będziemy musieli zmienić zachowanie bash za pomocą polecenia:

shopt -s dotglob

Aby mieć pewność, że ta zmiana zachowania utrzyma się po ponownym uruchomieniu, za pomocą tego polecenia możesz utworzyć w folderze plik wildcard.sh /etc/profile.d (Być może twoja dystrybucja ma inny folder).

A jeśli w katalogu źródłowym nie ma plików, powłoka nie będzie mogła niczym zastąpić gwiazdki, a kopiowanie również zakończy się błędem. Istnieją opcje przeciwdziałające tej sytuacji failglob и nullglob. Będziemy musieli ustawić failglob, co uniemożliwi wykonanie polecenia. nullglob nie będzie działać, ponieważ konwertuje ciąg znaków ze znakami wieloznacznymi, który nie znalazł dopasowania, na pusty ciąg znaków (długość zerowa), co dla cp spowoduje błąd.

Jeśli jednak w folderze znajdują się tysiące plików lub więcej, należy całkowicie porzucić podejście oparte na symbolach wieloznacznych. Fakt jest taki bash rozwija symbole wieloznaczne do bardzo długiego wiersza poleceń, takiego jak:

cp -a /souce/a /source/b /source/c …… /target

Istnieje ograniczenie długości linii poleceń, o czym możemy dowiedzieć się za pomocą polecenia:

getconf ARG_MAX

Uzyskajmy maksymalną długość linii poleceń w bajtach:

2097152

Или:

xargs --show-limits

Otrzymujemy coś takiego:

….
Maximum length of command we could actually use: 2089314
….

Pozbądźmy się więc całkowicie symboli wieloznacznych.

Po prostu napiszmy

cp -a /source /target

I tu mamy do czynienia z niejednoznacznością zachowań cp. Jeśli folder /target nie istnieje, otrzymamy to, czego potrzebujemy.

Jeśli jednak folder docelowy istnieje, pliki zostaną skopiowane do folderu /target/source.

Nie zawsze nie możemy wcześniej usunąć folderu /target, ponieważ może on zawierać potrzebne nam pliki, a naszym celem jest na przykład uzupełnienie plików w /target plikami z /source.

Jeśli foldery źródłowy i docelowy miały takie same nazwy, np. kopiowaliśmy z /source do /home/source, wówczas moglibyśmy użyć polecenia:

cp -a /source /home

Po skopiowaniu pliki w /home/source zostaną uzupełnione plikami z /source.

Jest to problem logiczny: możemy dodać pliki do katalogu docelowego, jeśli foldery mają takie same nazwy, ale jeśli są różne, to folder źródłowy zostanie umieszczony w katalogu docelowym. Jak skopiować pliki z/source do/target za pomocą cp bez symboli wieloznacznych?

Aby obejść to szkodliwe ograniczenie, stosujemy nieoczywiste rozwiązanie:

cp -a /source/. /target

Ci, którzy znają DOS i Linux, już wszystko zrozumieli: w każdym folderze znajdują się 2 niewidoczne foldery „”. i „..”, które są pseudofolderami i łączami do bieżących i wyższych katalogów.

  • podczas kopiowania cp sprawdza istnienie i próbuje utworzyć /target/.
  • Taki katalog istnieje i jest to /target
  • Pliki z /source są poprawnie kopiowane do /target.

Powieś go więc w pogrubionej ramce w swojej pamięci lub na ścianie:

cp -a /source/. /target

Zachowanie tego polecenia jest jasne. Wszystko będzie działać bez błędów, niezależnie od tego, czy masz milion plików, czy nie ma ich wcale.

odkrycia

Jeśli chcesz skopiować wszystko plików z jednego folderu do drugiego, nie używamy symboli wieloznacznych, lepiej je zamiast tego użyć cp w połączeniu z kropką na końcu folderu źródłowego. Spowoduje to skopiowanie wszystkich plików, w tym ukrytych, i nie zakończy się niepowodzeniem w przypadku milionów plików lub żadnego pliku.

Posłowie

vmspike zasugerował wersję polecenia z podobnym wynikiem:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

UWAGA: wielkość liter T ma znaczenie. Jeśli to pomieszasz, otrzymasz kompletną bzdurę: zmieni się kierunek kopiowania.
Podziękowanie:

  • Firmy RUVDS.COM za wsparcie i możliwość publikacji na swoim blogu w serwisie Habré.
  • Na obraz Potrójna koncepcja. Obraz jest bardzo duży i szczegółowy, można go otworzyć w osobnym oknie.

PS Wszelkie zauważone błędy proszę przesyłać w wiadomości prywatnej. Zwiększam za to swoją karmę.

Polecenie cp: poprawne kopiowanie folderów plików w *nix

Źródło: www.habr.com

Dodaj komentarz