Polecenie cp: poprawne kopiowanie folderów z plikami w *nix

Polecenie cp: poprawne kopiowanie folderów z plikami w *nix

W tym artykule omówione zostaną pewne niewidoczne aspekty związane z wykorzystaniem wildcardów podczas kopiowania, niejednoznaczne zachowanie polecenia cp przy kopiowaniu, a także sposoby pozwalające na poprawne kopiowanie ogromnej liczby plików bez pominięć i błędów.

Załóżmy, że musimy skopiować wszystko z folderu /source do folderu /target.

Pierwsze, co przychodzi do głowy, to:

cp /source/* /target

Od razu poprawimy to polecenie na:

cp -a /source/* /target

Klucz -a doda kopię wszystkich atrybutów, praw i włączy rekursję. Gdy nie jest wymagane dokładne odtworzenie praw, wystarczy klucz -r.

Po skopiowaniu stwierdzimy, że nie wszystkie pliki zostały skopiowane - zignorowane zostały pliki zaczynające się od kropki, takie jak:

.profil
.lokalny
.mc

i tym podobne.

Dlaczego tak się stało?

Ponieważ wildcardy są przetwarzane przez powłokę (bash w standardowym przypadku). Domyślnie bash ignoruje wszystkie pliki zaczynające się od kropek, uznając je za ukryte. Aby uniknąć takiego zachowania, musimy zmienić zachowanie bash za pomocą polecenia:

shopt -s dotglob

Aby ta zmiana zachowania zachowała się po restarcie, można stworzyć plik wildcard.sh z tym poleceniem w folderze /etc/profile.d (możliwe, że w Twojej dystrybucji jest inny folder).

A jeśli w katalogu źródłowym nie ma plików, to powłoka nie będzie mogła zastąpić gwiazdki, a kopiowanie zakończy się błędem. Na taką sytuację są opcje failglob i nullglob. Będziemy potrzebować ustawić failglob, która nie pozwoli na wykonanie polecenia. nullglob nie zadziała, ponieważ przekształca ciąg z wildcardami, które nie znalazły dopasowania, w pusty ciąg (o zerowej długości), co dla cp spowoduje błąd.

Jednakże, jeśli w folderze jest tysiące plików lub więcej, warto zrezygnować z podejścia z wildcardami. Chodzi o to, że bash rozwinie wildcardy w bardzo długą linię poleceń, podobną do:

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

Na długość linii poleceń są ograniczenia, które możemy poznać przy użyciu polecenia:

getconf ARG_MAX

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

2097152

Lub:

xargs --show-limits

Otrzymamy coś w rodzaju:

….
Maksymalna długość polecenia, które możemy właściwie użyć: 2089314
….

Zatem, pozbądźmy się całkowicie wildcardów.

Po prostu napiszmy

cp -a /source /target

A tutaj napotkamy na niejednoznaczność zachowania cp. Jeśli katalog /target nie istnieje, otrzymamy to, czego potrzebujemy.

Jednakże, jeśli folder docelowy istnieje, pliki zostaną skopiowane do folderu /target/source.

Nie zawsze możemy wcześniej usunąć folder /target, ponieważ mogą się w nim znajdować potrzebne nam pliki, a naszym celem jest, powiedzmy, uzupełnienie plików w /target plikami z /source.

Gdyby foldery źródłowy i docelowy nazywały się tak samo, na przykład, gdybyśmy kopiowali z /source do /home/source, moglibyśmy użyć polecenia:

cp -a /source /home

I po skopiowaniu pliki w /home/source byłyby uzupełnione plikami z /source.

Oto logiczna zagadka: możemy uzupełnić pliki w katalogu docelowym, jeśli foldery mają te same nazwy, ale jeśli się różnią, folder źródłowy zostanie umieszczony wewnątrz katalogu docelowego. Jak skopiować pliki z /source do /target za pomocą cp bez użycia wildcardów?

Aby obejść to niekorzystne ograniczenie, używamy nieoczywistego rozwiązania:

cp -a /source/. /target

Ci, którzy dobrze znają DOS i Linux, już wszystko rozumieją: w każdym folderze znajdują się dwa ukryte foldery «.» i «..», które są pseudokatalogami-linkami do bieżącego i wyższego katalogu.

  • Podczas kopiowania cp sprawdza istnienie i stara się stworzyć /target/.
  • Taki katalog istnieje i jest to /target.
  • Pliki z /source zostały poprawnie skopiowane do /target.

Zatem zapisz w pamięci lub na ścianie:

cp -a /source/. /target

Zachowanie tego polecenia jest jednoznaczne. Wszystko zadziała bez błędów, niezależnie od tego, czy masz milion plików, czy ich nie masz.

Wnioski

Jeśli trzeba skopiować wszystkie pliki z jednego folderu do drugiego, nie używamy wildcardów, zamiast tego lepiej użyć cp w połączeniu z kropką na końcu folderu źródłowego. To skopiuje wszystkie pliki, w tym ukryte, i nie zawiedzie przy milionach plików lub ich braku.

Epilog

vmspike zapropnował podobną do rezultatu wersję polecenia:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

UWAGA: wielkość liter T ma znaczenie. Jeśli się pomylisz, otrzymasz całkowity bałagan: kierunek kopiowania się zmieni.
Podziękowania:

  • Firmie RUVDS.COM za wsparcie i możliwość publikacji na swoim blogu na Habra.
  • Za obraz TripletConcept. Obrazek jest bardzo duży i szczegółowy, można go otworzyć w osobnym oknie.

P.S. Zgłaszane błędy proszę kierować na priv. Podnoszę za to karmę.

Polecenie cp: poprawne kopiowanie folderów z plikami w *nix

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster