znaleźć nazwy plików NIE kończące się konkretnymi rozszerzeniami na Uniksie?

207

Czy istnieje prosty sposób rekurencyjnego wyszukiwania wszystkich plików w hierarchii katalogów, które nie kończą się na liście rozszerzeń? Np. Wszystkie pliki, które nie są * .dll lub * .exe

Znalezienie systemu UNIX / GNU, mimo że potężne, nie wydaje się mieć excludetrybu (lub go brakuje) i zawsze trudno mi było używać wyrażeń regularnych do znajdowania rzeczy, które nie pasują do określonego wyrażenia .

Jestem w środowisku Windows (korzystam z portu GnuWin32 większości narzędzi GNU), więc jestem równie otwarty na rozwiązania tylko dla Windows.

Cristian Diaconescu
źródło

Odpowiedzi:

343

Lub bez (i potrzeba ucieczki:

find . -not -name "*.exe" -not -name "*.dll"

i aby również wykluczyć listę katalogów

find . -not -name "*.exe" -not -name "*.dll" -not -type d

lub w logice pozytywnej ;-)

find . -not -name "*.exe" -not -name "*.dll" -type f
Wytrzymały
źródło
6
-notmożna zastąpić '!'(Cytat jest zalecany). Z drugiej strony -namerozróżnia małe i wielkie litery, podczas gdy wielkość -inameliter nie ma znaczenia.
Ivan Chau,
45
find . ! \( -name "*.exe" -o -name "*.dll" \)
Chen Levy
źródło
2
Na Solarisie -notjest złą opcją, ta z !dobrym działaniem :)
DmitrySandalov
8
$ find . -name \*.exe -o -name \*.dll -o -print

Pierwsze dwie opcje dwóch nazw nie mają opcji -print, więc zostały pominięte. Cała reszta jest drukowana.

Jeff Ferland
źródło
4

Możesz coś zrobić za pomocą polecenia grep:

find . | grep -v '(dll|exe)$'

Zaznaczona -vflaga grepoznacza „znajdź rzeczy, które nie pasują do tego wyrażenia”.

VoteyDisciple
źródło
6
grep -v '\. (dll | exe) $' zapobiegałby na przykład dopasowaniu pliku lub katalogu o nazwie „dexe”
drAlberT
Działa to tylko z rozszerzonym wyrażeniem regularnym. Musiałem dodać -E (lub użyć egrep), aby to zadziałało.
żartuje
2

jeszcze jeden :-)

$ ls -ltr
razem 10
-rw-r - r-- 1 scripter linuxdumb 47 grudnia 23 14:46 test1
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:40 test4
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:40 test3
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:40 test2
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:41 plik 5
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:41 plik 4
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:41 plik 3
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:41 plik2
-rw-r - r-- 1 scripter linuxdumb 0 4 stycznia 23:41 plik 1
$ znajdź. -typ f! -nazwa „* 1”! -nazwa „* 2” -print
./test3
./test4
./file3
./file4
./file5
$

Odwołanie do polecenia Unix find

logika
źródło
1
find  /data1/batch/source/export   -type f -not  -name "*.dll" -not -name "*.exe"
gwecho huang
źródło
1

Linux / OS X:

Począwszy od bieżącego katalogu, rekurencyjnie znajdź wszystkie pliki z rozszerzeniem .dll lub .exe

find . -type f | grep -P "\.dll$|\.exe$"

Zaczynając od bieżącego katalogu, rekurencyjnie znajdź wszystkie pliki, które NIE kończą się na .dll lub .exe

find . -type f | grep -vP "\.dll$|\.exe$"

Uwagi:

(1) Opcja P w grep wskazuje, że używamy stylu Perla do pisania naszych wyrażeń regularnych do użycia w połączeniu z poleceniem grep . W celu wykonania polecenia grep w połączeniu z wyrażeniami regularnymi uważam, że styl Perla jest najpotężniejszym stylem na świecie.

(2) Opcja v w grep instruuje powłokę, aby wykluczyła dowolny plik, który spełnia wyrażenie regularne

(3) Znak $ na końcu powiedz „.dll $” jest znakiem kontrolnym ogranicznika, który informuje powłokę, że ciąg nazwy pliku kończy się na „.dll”

Wietnam Phuvan
źródło
0

Inne rozwiązania na tej stronie nie są pożądane, jeśli masz długą listę rozszerzeń - utrzymywanie długiej sekwencji -not -name 'this' -not -name 'that' -not -name 'other'byłoby żmudne i podatne na błędy - lub jeśli wyszukiwanie jest programowe, a lista rozszerzeń jest tworzona w czasie wykonywania.

W takich sytuacjach findpożądane może być rozwiązanie, które jaśniej oddziela dane (listę rozszerzeń) i kod (parametry do ). Biorąc pod uwagę strukturę katalogu i plików, która wygląda następująco:

.
└── a
    ├── 1.txt
    ├── 15.xml
    ├── 8.dll
    ├── b
    │   ├── 16.xml
    │   ├── 2.txt
    │   ├── 9.dll
    │   └── c
    │       ├── 10.dll
    │       ├── 17.xml
    │       └── 3.txt
    ├── d
    │   ├── 11.dll
    │   ├── 18.xml
    │   ├── 4.txt
    │   └── e
    │       ├── 12.dll
    │       ├── 19.xml
    │       └── 5.txt
    └── f
        ├── 13.dll
        ├── 20.xml
        ├── 6.txt
        └── g
            ├── 14.dll
            ├── 21.xml
            └── 7.txt

Możesz zrobić coś takiego:

## data section, list undesired extensions here
declare -a _BADEXT=(xml dll)

## code section, this never changes
BADEXT="$( IFS="|" ; echo "${_BADEXT[*]}" | sed 's/|/\\|/g' )"
find . -type f ! -regex ".*\.\($BADEXT\)"

Co skutkuje w:

./a/1.txt
./a/b/2.txt
./a/b/c/3.txt
./a/d/4.txt
./a/d/e/5.txt
./a/f/6.txt
./a/f/g/7.txt

Możesz zmienić listę rozszerzeń bez zmiany bloku kodu.

UWAGA nie działa z natywnym OSX find- zamiast tego użyj gnu find.

Chris Johnson
źródło