Odpowiedzi:
Uwaga: Ta odpowiedź dotyczy Basha, ale w dużej mierze dotyczy pytania dotyczącego globalnych wzorców!
Znak gwiazdy ( *
) to symbol wieloznaczny. Istnieje pewien zestaw znaków, który zajmie miejsce, a pierwszy znak będący kropką ( .
) nie jest jednym z nich. Jest to szczególny przypadek tylko ze względu na to, jak działają systemy plików Uniksa, pliki zaczynające się od kropki są uważane za „ukryte”. Oznacza to, że narzędzia takie jak cp
, ls
itp nie „widzą” je, chyba że wyraźnie powiedziano, aby to zrobić.
Najpierw stwórzmy przykładowe dane.
$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}
Więc teraz mamy następujące:
$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3
Teraz zagrajmy w kilka gier. Możesz użyć polecenia, echo
aby wyświetlić listę konkretnych symboli wieloznacznych ( *
) dla danego polecenia, takich jak:
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3
$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3
$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2
$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
$ echo .dotdir*
.dotdir1 .dotdir2
Możesz użyć tego polecenia, shopt -s dotglob
aby zmienić zachowanie *
tak, aby oprócz podobnych plików regfile1
również pasowały .dotfile1
.
fragment strony bash
man
dotglob If set, bash includes filenames beginning with a `.' in the results
of pathname expansion.
Przykład:
$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Możesz przywrócić to zachowanie za pomocą tego polecenia:
$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3
Dla ciebie mówisz cp
, że chcesz skopiować wszystkie pliki, które pasują do wzorca *
, i nie ma żadnych plików.
$ cp foo/.* .
Możesz to zrobić, jeśli chcesz wszystko w foo
folderze:
$ cp foo .
Lub możesz wyrazić się jasno:
$ cp foot/.* foo/* .
Bardziej kompaktowa forma wykorzystująca rozszerzenie nawiasów w bash
:
$ cp foo/{.,}* .
W dowolnym momencie możesz użyć tej echo
sztuczki, aby zobaczyć, jakie są proponowane wzorce plików (to fantazyjne określenie tego, co jest częścią gwiazdy).
$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3
Nawiasem mówiąc, jeśli zamierzasz skopiować katalog plików + inne katalogi, zwykle chcesz to zrobić rekurencyjnie, to jest -R
przejście do cp
:
$ cp -R foo/. .
shopt -s dotglob
, echo *
a następnie daje:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
cp -r foo .
zazwyczaj nie będzie działać, ponieważ cp
odmówi kopiowania foo
nad sobą, prawdopodobnie miałeś na myśli cp -R foo/. .
. (zwróć uwagę, że cp -R
jest to standard).
zsh
nie obejmuje .
i nie ..
rozwija .*
. W zsh
przypadku, gdy wzorzec nie pasuje, polecenie zostanie przerwane (całkiem rozsądnie ponownie), więc w ogólnym przypadku cp foo/{,.}* .
zakończy się niepowodzeniem, jeśli nie będzie żadnych ukrytych plików lub nie ukrytych plików.
shopt
nie istnieje.
Za pomocą zsh
, typowym sposobem jest użycie D
kwalifikatora glob (aby dołączyć pliki [D] ot):
cp foo/*(D) .
Zauważ, że z lub bez D
globs zsh nigdy nie zawiera .
ani ..
(jak można się spodziewać).
Powłoka traktuje te pliki jako ukryte, kiedy rozpoznaje *
znak, więc cp
nie otrzymuje żadnej z tych nazw plików jako argumentów.
Możesz je skopiować, wyraźnie zaznaczając cp foo/.* .
Jeśli chcesz skopiować wszystkie pliki i katalogi z jednego miejsca do drugiego, możesz użyć standardowego rsync
polecenia. W podanym powyżej przykładzie:
mkdir foo && touch foo/.test
rsync -a foo/ .
będzie rekurencyjnie kopiować całą zawartość foo
, w tym ukryte pliki i ukryte katalogi, do bieżącego katalogu. Końcowy ukośnik na końcu foo/
jest ważny dla rsync; z nim foo
kopiowana jest tylko zawartość pliku, bez niego rsync również skopiuje foo
. Na przykład:-
mkdir src && mkdir dest && touch src/.test
rsync -a src dest // copies 'src' contents to 'dest/src'
rsync -a src/ dest // copies 'src' contents to 'dest'
Istnieje wiele innych opcji dostrojenia rsync, w tym kopiowanie między komputerami.
dotglob
jest tłumaczoneglobdots
przez zsh, który jest niepoprawną nazwą opcji dla bash .