Jak skopiować plik o nazwie zaczynającej się od kropki?

26

Próbuję skopiować wszystkie pliki z katalogu A do katalogu B. Wszystkie pliki w katalogu A zaczynają się od kropki, na przykład:

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

które znalazłem, jeśli używam:, cp A/* Bzawsze pojawia się błąd:

cp: cannot stat 'A/*': no such file or directory

Wydaje się, nie ma opcji na cpjak lsobsługiwać wpisów rozpoczętych z kropką, ktoś ma pomysł jak to naprawić?

użytkownik59285
źródło

Odpowiedzi:

34

Powodem jest to, że in bash, *nie obejmuje plików zaczynających się od kropki ( .).

Możesz biegać

cp A/.* B

Będzie cię ostrzec, że nie kopiować .lub ..czy jakieś podkatalogi, ale to jest w porządku.

Lub, jeśli chcesz skopiować pliki kropkowe i normalne pliki, uruchom

cp A/.* A/* B

Możesz także biec

shopt -s dotglob
cp A/* B

które będą działać bash, ale nie sh.

A jeśli nie masz nic przeciwko kopiowaniu podkatalogów, jest to najłatwiejsze:

cp -R A/ B

Wskazówka: jeśli kiedykolwiek symbole wieloznaczne nie działają zgodnie z oczekiwaniami, spróbuj uruchomić je za pomocą echa, np

$ echo A/*
A/file1 A/file2

$ echo A/.*
A/. A/.. A/.hidden1 A/.hidden2

$ echo A/.* A/*
A/. A/.. A/.hidden1 A/.hidden2 A/file1 A/file2

$ shopt -s dotglob
$ echo A/*
A/file1 A/file2 A/.hidden1 A/.hidden2
Mikel
źródło
To tylko problem, jeśli używasz -r. Bez -rtego po prostu pominie katalogi.
Mikel
I przykład, który podam za pomocą -Rpowinien również działać dobrze. Jeśli uważasz, że to źle, wyjaśnij dlaczego.
Mikel
7

Jeśli bash, możesz ustawić dotglobprzed skopiowaniem

shopt -s dotglob
cp A/* /destination

Lub język programowania

$ ruby -rfileutils -e  'Dir[".*"].each {|x| FileUtils.copy(x,"/destination") if File.file?x}'

Jeśli nie chcesz ustawiać dotglob, po prostu

cp A/.* /destination 2>/dev/null

źródło
Użycie dotglob OP spowoduje także skopiowanie wszystkich nie ukrytych plików, czego nie chce.
peoro
@peoro, powinieneś ponownie przeczytać pytanie. Wszystkie pliki Asą ukryte. Po prostu chce to skopiować.
7

To, czego szukasz, jest bardziej podobne do:

cp A/.??* B/

Spowoduje to dopasowanie wszystkich plików dot, ale nie „.” lub „..”. Większość powyższych rozwiązań jest w porządku, o ile nie pracujesz rekurencyjnie. Ale gdy tylko zechcesz zrobić coś takiego:

cp -R A/.??* B/

Bez pomijania „..” skopiujesz wszystko z katalogu nadrzędnego w dół, w tym pliki inne niż dotfile.

John Westlund
źródło
1
Pominie to pliki kropek, które są pojedynczymi znakami, takimi jak .alub .x. Najkrótszy znaleziony przeze mnie wzór globowania, który pasuje do każdego pliku kropki oprócz .i ..jest .[^.]*.
pavon
2

Właśnie próbowałem następujące i to działa po prostu znaleźć ...

cp A/.* B/
Andrew White
źródło
2
To również przejdzie A/.i A/..jako parametry do cp, co może być problematyczne w przypadku, gdy OP również musi skopiować katalogi (używając cp -r)
peoro
2

To nie cpjest wina , to bash: bash rozwija się *we wszystkich nie ukrytych .plikach (tzn. Nie zaczyna się od ).

Bash będzie się rozwijał .*(tak jak A/.*w twoim przypadku) ze wszystkimi plikami zaczynającymi się od ., ale na szczęście zawiera także .i ..(katalogi bieżący i nadrzędny), które prawdopodobnie będziesz chciał pominąć. (Zauważ, że inne powłoki, takie jak zsh, nie obejmowałyby ich, a IIRC również bash, po ustawieniu niektórych opcji).

Łatwym rozwiązaniem może być usunięcie .i ..dopasowanie plików .*w (bardzo) hackerski sposób:

cp $( for F in A/.*; do echo $F | grep -v "^\.*$"; done ) B

lub ten (prawdopodobnie czystszy: używa finddo znalezienia plików do skopiowania):

cp $( find A -maxdepth 1 -mindepth 1 -name ".*" ) B

ale prawdopodobnie znajdziesz czystsze rozwiązania.

peoro
źródło
dlaczego powinieneś użyć for loopa następnie stworzyć dodatkowy grepproces tylko po to, aby wykonać taką pracę cp A/.*? cpzignoruje „.” i katalogi „..”.
1

Jeśli wszystkie zaczynają się od kropki, po prostu użyj A/.*:

[holt@Michaela test]$ cp A/* B
cp: cannot stat `A/*': No such file or directory

[holt@Michaela test]$ cp A/.* B
cp: omitting directory `A/.'
cp: omitting directory `A/..'
[holt@Michaela test]$ ls -al B
total 8
drwxrwxr-x. 2 holt holt 4096 2011-03-31 16:57 .
drwxrwxr-x. 4 holt holt 4096 2011-03-31 16:57 ..
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .a
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .b
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .c

Mam nadzieję że to pomoże!

Xavier Holt
źródło
1

Możesz użyć tego skryptu

IFS = $ '\ n'; dla aktu w $ (znajdź A -d 1); wykonaj cp -R „$ act” B; gotowy

teki
źródło
0

Kopiuj:

cp A/.* B

lista:

ls -l A/.*

wyświetla listę plików bez malejących katalogów:

ls -ld A/.*
Błogosławiony Geek
źródło
0

Musisz wykluczyć. i .. z listy plików przekazanej do cp!

To jest bezpieczne:

ls -1d A/.[a-zA-Z]* | xargs -i cp -rp {} B
AmitP
źródło
0

To jest stary wątek ... ale zawsze byłem w stanie skopiować wszystkie pliki. W tym pliki / foldery zaczynające się od „.”

Przykład skopiuje wszystkie pliki i foldery:

cp -aup /root/.* / backup / root /

Ontologik
źródło