Powiedzmy, że chcę skopiować zawartość katalogu z wyjątkiem plików i folderów, których nazwy zawierają słowo „Muzyka”.
cp [exclude-matches] *Music* /target_directory
Co powinno zostać zastąpione przez [wykluczające mecze], aby to osiągnąć?
bash
shell
pattern-matching
glob
użytkowników4812
źródło
źródło
ls /dir/*/!(base*)
f
, opróczfoo
?Opcja
extglob
powłoki zapewnia mocniejsze dopasowanie wzorców w wierszu poleceń.Włączasz za pomocą
shopt -s extglob
i wyłączasz za pomocąshopt -u extglob
.W twoim przykładzie początkowo zrobiłbyś:
Pełne dostępny ext zakończył glob operatorzy Bing są (fragment
man bash
):Na przykład, jeśli chcesz wyświetlić listę wszystkich plików w bieżącym katalogu, które nie są
.c
lub.h
pliki, wykonaj następujące czynności:Oczywiście działa normalne globowanie powłoki, więc ostatni przykład można również zapisać jako:
źródło
.c
lub.h
jest katalogiem.D
, ale nie zawartość podkatalogów, które mogą się w nim znajdowaćD
.Nie w bashu (o którym wiem), ale:
Wiem, że nie było to dokładnie to, czego szukałeś, ale to rozwiąże twój przykład.
źródło
Jeśli chcesz uniknąć kosztów memu korzystania z polecenia exec, uważam, że lepiej poradzisz sobie z xargs. Myślę, że poniższe jest bardziej wydajną alternatywą dla
źródło
W bash alternatywą
shopt -s extglob
jestGLOBIGNORE
zmienna . To nie jest naprawdę lepsze, ale łatwiej mi zapamiętać.Przykładem może być to, czego chciał oryginalny plakat:
Po zakończeniu ,
unset GLOBIGNORE
aby móc to zrobićrm *techno*
w katalogu źródłowym.źródło
Możesz także użyć dość prostej
for
pętli:źródło
-maxdepth 1
do nierekurencyjnych?find
w backtickach spowoduje nieprzyjemne działanie, jeśli znajdzie jakieś nietrywialne nazwy plików.Osobiście wolę używać grep i komendy while. Pozwala to pisać potężne, ale czytelne skrypty, zapewniając, że skończysz robić dokładnie to, co chcesz. Ponadto za pomocą polecenia echa można wykonać próbę przed rozpoczęciem rzeczywistej operacji. Na przykład:
wydrukuje pliki, które skończysz kopiować. Jeśli lista jest poprawna, następnym krokiem jest po prostu zastąpienie polecenia echo poleceniem kopiowania w następujący sposób:
źródło
bash
można użyćwhile IFS='' read -r filename
, ale wtedy nowe linie są nadal problemem. Zasadniczo najlepiej nie używaćls
do wyliczania plików; narzędzia takiefind
są znacznie lepiej dostosowane.for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; done
Sztuczka Nie widziałem tu jeszcze, że nie używa
extglob
,find
czygrep
jest w leczeniu dwie listy plików jak zestawy i „diff” je za pomocącomm
:comm
jest lepszy niż,diff
ponieważ nie ma dodatkowego cruft.Zwraca wszystkie elementy zestawu 1
ls
, które również nie znajdują się w zestawie 2ls *Music*
,. Wymaga to, aby oba zestawy były posortowane, aby działały poprawnie. Nie ma problemuls
i globalnej ekspansji, ale jeśli używasz czegoś podobnegofind
, pamiętaj, aby wywołaćsort
.Potencjalnie przydatne.
źródło
comm -23 <(ls) exclude_these.list
Jedno rozwiązanie tego można znaleźć w find.
Znajdź ma wiele opcji, możesz uzyskać dość szczegółowe informacje na temat tego, co dołączasz i wykluczasz.
Edytuj: Adam w komentarzach zauważył, że jest to rekurencyjne. znajdź opcje mindepth i maxdepth mogą być przydatne w kontrolowaniu tego.
źródło
find -maxdepth 1 -not -name '*Music*'
/Poniższe prace zawierają listę wszystkich
*.txt
plików w bieżącym katalogu, z wyjątkiem plików zaczynających się na liczbę.To działa w
bash
,dash
,zsh
a wszystkie inne kompatybilne muszle POSIX.W pierwszym wierszu wzorzec
/some/dir/*.txt
spowodujefor
iterację pętli po wszystkich plikach,/some/dir
których nazwa kończy się na.txt
.W drugim wierszu zastosowano instrukcję case, aby usunąć niepożądane pliki. -
${FILE##*/}
Wyrażenie usuwa wszystkie wiodące komponenty nazwy katalogu z nazwy pliku (tutaj/some/dir/
), dzięki czemu wzory mogą pasować tylko do nazwy basena pliku. (Jeśli usuwasz tylko nazwy plików na podstawie sufiksów, możesz$FILE
zamiast tego skrócić ).W linii trzeciej wszystkie pliki pasujące do
case
wzorca[0-9]*
zostaną pominięte (continue
instrukcja przeskoczy do następnej iteracjifor
pętli). - Jeśli chcesz, możesz zrobić coś bardziej interesującego, np. Pominąć wszystkie pliki, które nie zaczynają się na literę (a – z)[!a-z]*
, lub możesz użyć wielu wzorców, aby pominąć kilka rodzajów nazw plików, np.[0-9]*|*.bak
Pominąć pliki oba.bak
pliki oraz pliki, które nie zaczynają się od liczby.źródło
*.txt
zamiast po prostu*
). Naprawiono teraz.to zrobiłoby to wykluczając dokładnie „Muzykę”
to i to za wykluczenie takich rzeczy jak Muzyka? * lub *? Muzyka
źródło
cp
podręcznika w systemie MacOS ma-a
opcję, ale robi coś zupełnie innego. Która platforma to obsługuje?