найти имена файлов, НЕ заканчивающиеся конкретными расширениями в Unix?

207

Есть ли простой способ рекурсивного поиска всех файлов в иерархии каталогов, которые не заканчиваются в списке расширений? Например, все файлы, которые не являются * .dll или * .exe

UNIX / GNU find, как бы он ни был мощен, похоже, не имеет excludeрежима (или я его упускаю), и мне всегда было трудно использовать регулярные выражения для поиска вещей, которые не соответствуют определенному выражению ,

Я нахожусь в среде Windows (использую порт GnuWin32 большинства инструментов GNU), поэтому я в равной степени открыт для решений только для Windows.

Кристиан Дьяконеску
источник

Ответы:

343

Или без него (и от него надо спасаться

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

а также исключить список каталогов

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

или в позитивной логике ;-)

find . -not -name "*.exe" -not -name "*.dll" -type f
выносливый
источник
6
-notМожет быть заменено на '!'(Цитата рекомендуется). С другой стороны, -nameчувствителен к регистру, а -inameнечувствителен к регистру.
Иван Чау
45
find . ! \( -name "*.exe" -o -name "*.dll" \)
Чен Леви
источник
2
На Солярисе -notплохой вариант, этот с !хорошо работает :)
DmitrySandalov
8
$ find . -name \*.exe -o -name \*.dll -o -print

У первых двух опций -name нет опции -print, поэтому они пропущены. Все остальное напечатано.

Джефф Ферланд
источник
4

Вы можете сделать что-нибудь, используя команду grep:

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

Этот -vфлаг grepспециально означает «найти вещи, которые не соответствуют этому выражению».

VoteyDisciple
источник
6
grep -v '\. (dll | exe) $' будет препятствовать повторному сопоставлению, например, файла или каталога с именем "dexe"
drAlberT
Это работает только с расширенным регулярным выражением. Мне пришлось добавить -E (или использовать egrep), чтобы сделать эту работу.
Джоут
2

еще один :-)

$ ls -ltr
всего 10
-rw-r - r-- 1 сценарий linuxdumb 47 23 декабря 14:46 test1
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:40 test4
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:40 test3
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:40 test2
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:41 file5
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:41 file4
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:41 file3
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:41 file2
-rw-r - r-- 1 сценарий linuxdumb 0 4 января 23:41 file1
$ найти. Тип F! имя "* 1"! -принт "* 2" -принт
./test3
./test4
./file3
./file4
./file5
$

Unix найти ссылку на команду

логика
источник
1
find  /data1/batch/source/export   -type f -not  -name "*.dll" -not -name "*.exe"
гвехо хуан
источник
1

Linux / OS X:

Начиная с текущего каталога, рекурсивно найдите все файлы, заканчивающиеся на .dll или .exe

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

Начиная с текущего каталога, рекурсивно находите все файлы, которые НЕ заканчиваются в .dll или .exe

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

Ноты:

(1) Опция P в grep указывает, что мы используем стиль Perl для написания наших регулярных выражений, которые будут использоваться вместе с командой grep . В целях исключения команды grep в сочетании с регулярными выражениями я обнаружил, что стиль Perl является наиболее мощным стилем.

(2) Опция v в grep указывает оболочке исключить любой файл, который удовлетворяет регулярному выражению

(3) Символ $ в конце слова «.dll $» является управляющим символом-разделителем, который сообщает оболочке, что строка имени файла заканчивается на «.dll».

Вьетнхи пуван
источник
0

Другие решения на этой странице нежелательны, если у вас длинный список расширений - поддержание длинной последовательности -not -name 'this' -not -name 'that' -not -name 'other'будет утомительным и подверженным ошибкам - или если поиск является программным, а список расширений создается во время выполнения.

Для этих ситуаций findможет быть желательно решение, которое более четко разделяет данные (список расширений) и код (параметры ). Учитывая структуру каталогов и файлов, которая выглядит следующим образом:

.
└── 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

Вы можете сделать что-то вроде этого:

## 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\)"

Что приводит к:

./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

Вы можете изменить список расширений без изменения блока кода.

NOTE не работает с родным OSX find- используйте вместо этого gnu find.

Крис Джонсон
источник