Jak skopiować ukryte (zaczynające się od kropki) pliki i podkatalogi w systemie Linux?

10

Jak skopiować ukryte pliki i ukryte podkatalogi (te zaczynające się od kropki) z folderu A do folderu B? Na przykład, jeśli mam tę strukturę:

A/a
A/b
A/.a
A/.b/
A/.b/somefile
A/.b/.c

Chciałbym skopiować do B tylko ukryte pliki i ukryte podkatalogi w A:

B/.a
B/.b/
B/.b/somefile
B/.b/.c

Próbowałem już tego polecenia: cp A/.* Bz tego innego pytania superużytkownika . Jednak nie kopiuje podkatalogów. Próbowałem też cp -r A/.* B, ale kopiuje, .więc kończę dokładną kopią A (w tym normalnych plików). Każda pomoc jest mile widziana.

gaboroncancio
źródło

Odpowiedzi:

16

Tak długo, jak szukasz ukrytych plików i folderów na poziomie A i na przykład nie chcesz

A/b/.hidden

do skopiowania, powinieneś móc użyć tego:

cp -r A/.[^.]* B

Zasadniczo oznacza to skopiowanie wszystkiego, co zaczyna się od a, .a następnie dowolnego znaku innego niż .To, który odfiltrowuje .i..

Edycja: Usunięto -p z polecenia cp, ponieważ Asker nie wskazał, że chce zachować własność, daty itp.

Wszechobecność
źródło
Działa to w przypadku przykładowych nazw plików i katalogów podanych w pytaniu, ale w tekście pytania jest napisane „ukryte pliki i ukryte podkatalogi (te zaczynające się od kropki)”, a ta odpowiedź nie znajdzie plików i katalogów, których nazwy zaczynają się od dwie kropki; np ..c.
Scott
To dość ostry przypadek, ale jednak uzasadniona obawa. Nie zastanawiałem się nad tym. Możesz to wyjaśnić, przełączając się na, .*[^.]ale wtedy przegapisz pliki, które kończą się na .. Myślę, że naprawdę potrzebujesz rozszerzonego globowania, aby naprawdę uwzględnić wszystkie przypadki.
Wszechobecność
4

Problem A/.*polega na tym, że istnieje katalog, .w Aktórym również pasuje do wzorca.

Możesz włączyć rozszerzone wzorce globów i użyć następujących opcji:

shopt -s extglob
cp -r A/.!(?(.)) B    

Pasuje do plików, których nazwa zaczyna się od kropki i których drugim znakiem nie jest ani kropka, ani nic (? (.) Nie pasuje do nic lub kropki,! (...) neguje to znaczy!! (? (.)) Pasuje do wszystkiego innego niż nic lub kropka).

choroba
źródło
+1 za poprawną odpowiedź. Zauważ, że .!(@(|.))jest to (AFAICT) równoważne z powyższym, (IMNSHO) jest trochę wyraźniejsze i tylko jedna postać jest dłuższa.
Scott
3

W takich przypadkach zaleca się użycie findzamiast cptego:

find A/ -type f -maxdepth 1 -name '.*' -exec cp -p {} B/ \;

Podstawowa składnia dzieli się następująco:

  • find A/ -type f: findelementy w katalogu, A/którego typem jest plik (zamiast katalogu)…
  • -maxdepth 1 -name '.*': Do tego dla jednego maxdepthz katalogów i od którego namezaczyna się ..
  • -exec cp -p {} B/ \;: A kiedy znajdują się te pliki, komenda z flagą zachować dat / razy od źródła ( ) do miejsca przeznaczenia .execcp-p{}B/

Lubię maxdepthdodawać warstwę kontrolną, więc nie kopiuję przypadkowo całego systemu plików. Ale możesz to usunąć.

JakeGould
źródło
0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d zapewnia listę rekurencyjną w obrębie A zawierającą tylko katalogi
  • grep -E "\." filtruje katalogi kropką (tzn. ukryte katalogi)
  • potrzebna była tutaj opcja -E, ponieważ bez niej oznacza to również „bieżący katalog”
  • odwrotnym ukośnikiem jest uniknięcie znaczenia wyrażenia „dowolny znak” w wyrażeniu regularnym
  • cp -r kopiować rekurencyjnie

Utworzyłem strukturę plików i folderów dla A i wykonałem polecenie w Git Bash (w tej chwili nie mam Linuksa) i zadziałało.

malarres
źródło
Dzieje się tak, jeśli pliki mają białe znaki lub znaki specjalne w nazwie lub ścieżce.
slhck
Dzięki za zauważenie :) Właściwie ograniczyłem się do „przypadku testowego” autorstwa @gaboroncancio. Jeśli możesz dać mi inną baterię testową, mogę spróbować to poprawić (oczywiście, jeśli chcesz,
popraw
Możesz po prostu umieścić pliki kropkowe w folderze o nazwie A B, a wtedy zadziałałoby to nieoczekiwanie, ponieważ rozwinąłoby się do cp -r A B/.dotfile B. Ogólna rada to w ogóle nie analizować findani lsgenerować wyników . Jeśli używasz find, powinieneś również użyć własnych opcji do filtrowania grep, a jeśli findprzesyłasz dane wyjściowe gdzie indziej, użyj -print0lub bezpośrednio wywołaj żądane polecenie. Zobacz find instrukcję .
slhck
Nawet bardziej ogólnie, podczas pracy z plikami najbezpieczniej jest używać globów powłoki, jak wyjaśniono w innych odpowiedziach (choć często wymagają extglobone ustawienia).
slhck
Dzięki za link. Zostawmy więc findparsowanie.
malarres
0

Alternatywnie możesz użyć tego innego polecenia, jeśli drugi znak jest alfanumeryczny ( źródło ):

cp -r A/.[a-zA-Z0-9]* B
gaboroncancio
źródło
Działa to w przypadku przykładowych nazw plików i katalogów podanych w pytaniu, ale w tekście pytania jest napisane „ukryte pliki i ukryte podkatalogi (te zaczynające się od kropki)”, a ta odpowiedź nie znajdzie plików i katalogów, których nazwy zaczynają się od kropka i znak specjalny; np . .@foolub ..c.
Scott
Dlatego wskazuję, że działa, jeśli drugi znak jest alfanumeryczny. ;)
gaboroncancio