Jak skopiować niektóre, ale nie wszystkie pliki?

54

Tak więc możesz używać *symbolu wieloznacznego dla wszystkich plików, gdy używasz go cpw kontekście katalogu. Czy istnieje sposób na skopiowanie wszystkich plików oprócz xpliku?

Chad Harrison
źródło

Odpowiedzi:

42

W bashmożesz użyć extglob:

 $ shopt -s extglob  # to enable extglob
 $ cp !(b*) new_dir/

gdzie !(b*)wyklucz wszystkie b*pliki.

Możesz później wyłączyć za extglobpomocą

 $ shopt -u extglob
wysypka
źródło
Czy wiesz, czy istnieje coś równoważnego dla powłoki tcsh?
Levon
Niestety nie. Wydaje się, że findto jedyny sposób na tcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
pośpiech
50

Rsync radzi sobie z tym ładnie.

Przykład skopiuj wszystko: rsync -aP /folder1/* /folder/2

Przykład skopiuj wszystko z wyłączeniem: rsync -aP --exclude=x /folder1/* /folder2/

-aPPrzełącznik:

a: Podobne do cp -arekurencyjnego itp. P: Pokazuje postęp, miłą cechę rsync.

Tim
źródło
5
I zobacz tę odpowiedź w celu uzyskania krótkiego przewodnika po popularnych listach wykluczeń rsync.
Gilles 'SO - przestań być zły'
1
W systemie darwin / MacOS używaj -rPzamiast, -aPjeśli chcesz się powtarzać. -asłuży do archiwizacji. Nie jestem pewien, czy to się zmieniło, czy po prostu inaczej na MacOS.
jpoveda
rsyncma opcję uczynienia go rekurencyjnym. Przykład: rsync --recursive -P --exclude=x /folder1/* /folder2/. (Testowane tylko na Ubuntu)
n1k31t4
12

To nie jest funkcja cp, jest to funkcja twojej powłoki (rozwija się tak, *że oznacza wszystkie pliki bez kropek), więc odpowiedź zależy od używanej powłoki . Na przykład zshobsługuje tę składnię:

$ cp ^x /path/to/destination

Gdzie ^xoznacza „wszystkie pliki oprócz x

Możesz także łączyć wzorce wyboru i usuwania zaznaczenia, np. Aby skopiować wszystkie pliki wav oprócz tych zawierających xyz, możesz użyć:

cp *.wav~*xyz*
Michał Mrożek
źródło
Jakieś komentarze na temat bash?
Chad Harrison
@hydroparadise Nie wiem dużo o bashu, ale ta odpowiedź wydaje się to obejmować
Michael Mrozek
Co z tcsh? Ktoś wie?
Levon
4

Można to również zrobić w zwykłej starej (przenośnej / kompatybilnej) powłoce Bourne'a na wiele sposobów za pomocą standardowych narzędzi w znacznie mniej elegancki sposób niż przy użyciu zaawansowanego globowania powłoki lub poleceń z wbudowanymi opcjami wykluczania.

Jeśli nie ma zbyt wielu plików (i nie zawiera nazw, w tym spacji i / lub podziałów wierszy), może to być sposób:

cp `ls | egrep -v '^excludename$'` destdir/.

Oczywiście bashnarzędzia GNU są świetne i wydajne, ale wciąż nie zawsze są dostępne. Jeśli zamierzasz umieścić go w przenośnym skrypcie, poleciłbym findjak w komentarzu Rush.

MattBianco
źródło
2
Uważam, że ostatnia część twojej odpowiedzi po prostu odwraca uwagę od tematu. Poza tym „Unix” nie jest już złotym standardem (jeśli w ogóle był). To po prostu nie jest istotne, jeśli coś jest „Unixowe” lub już nie, pomimo tego, że tytuł tej strony to „Unix i Linux”.
Alexander
2
DOBRZE. Zamiast tego przeniosłem tutaj komentarz: Unix to nie GNU. Zgadzam się, że „unikalność” rzeczy nie jest zbyt interesująca, ale nadal wierzę w przenośność i trochę wiem o twojej historii.
MattBianco
W pełni się z tobą zgódź.
Alexander
2

Jeśli chcesz skopiować wszystko z folderu (łącznie z podfolderami) do określonego podkatalogu:

cp -R $(ls | grep -v '^subdir$') subdir/

Działa z sh, bash, zsh (przynajmniej).

użytkownik2707671
źródło
1
Przekonaj mnie, że to nie to samo, cocp -R * subdir/
roaima,
1
Jeśli użyjesz tego polecenia „cp -R * subdir /”, bash / zsh spróbuje skopiować „subdir” rekurencyjnie. Kończy się błąd: „nazwa jest za długa (nie skopiowana)”.
user2707671
Słuszna uwaga. Twoja sugestia próbuje uniknąć ostrzeżenia z cp(nie z bash/ sh), „ cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’”. Kopiowanie jest jednak prawidłowe. Niestety twój wariant zrywa z każdą nazwą pliku zawierającą spację lub interpunkcję wrażliwą na powłokę. Zobacz unix.stackexchange.com/q/128985/135943
roaima
-1

extglob to chyba jak dotąd najlepszy sposób.

Innym sposobem jest użycie cp $(ls --ignore=x) subdir/

Edwin Lee
źródło
Spowoduje to uszkodzenie dowolnej postaci znaków specjalnych w nazwach plików. (Spacje, znaki nowego wiersza $itp.) Nigdy nie analizuj wyniku ls. unix.stackexchange.com/q/128985/135943
Wildcard