Как найти файлы с определенными расширениями, исключив некоторые имена только в текущем каталоге?

По крайней мере, в Ubuntu 1 , / var / run является символической ссылкой на / run

$ ls -l /var/run
lrwxrwxrwx 1 root root 4 Jun 29 14:05 /var/run -> /run

Команда find имеет два варианта которые управляют обработкой символических ссылок, как указано на странице руководства:

   -P     Never follow symbolic links.  This  is  the  default  behaviour.

   -L     Follow symbolic links.  

поэтому, когда вы запускали find / var / -name reboot-required , ссылка не переходила, и файл не был найден. Напротив, когда вы запускали find / var / run / -name reboot-required , поиск запускался с «другой стороны» символической ссылки (точно так же, как если бы вы выполнили find / run -name reboot-required ), поэтому файл был найден .

Добавление флага -L должно устранить двусмысленность, например

find -L /var/ -name reboot-required 2>/dev/null


] [1]. Фактически, похоже, это предусмотрено стандартом Linux FHS 3.0 .

2
07.12.2016, 09:55
4 ответа

С find :

find . ! -name . -prune \
    \( -name '*.ext1' -o -name '*.ext2' \) \
  ! \( -name 'name1.*' -o -name 'name2.*' \)

Использование -prune является стандартным эквивалентом GNU -maxdepth или некоторых BSD -depth (хотя эти BSD теперь также поддерживают -mindepth / -maxdepth à la GNU). Здесь он сообщает find не переходить ни в какой каталог, кроме . .

! -имя . также исключает . из выбора, так что ! -имя . -prune является стандартным эквивалентом GNU -mindepth 1 -maxdepth 1 или некоторых BSD -depth 1 . Для GNU -mindepth 1 (некоторые BSD - -depth -2 ) вы должны написать find. \ (-name. -o -prune \) .

С помощью zsh вы также можете сделать это:

setopt extendedglob
printf '%s\n' *.(ext1|ext2)~(name1|name2).*(D)

~ - оператор and-not, и (D) для включения точечных файлов.

4
27.01.2020, 21:56

В текущем каталоге вы можете использовать ls с grep (при условии, что имена ваших файлов не содержат символов новой строки):

ls -a | grep -E '\.ext(1|2)$' | grep -vE '^name(1|2)\.'
2
27.01.2020, 21:56

«Только в текущем каталоге» вам не нужно находить файлы, вы можете просто перечислить их (с обычными оговорками о возможности выявления странных имен файлов, содержащих интересные символы):

ls -d *.ext1 *.ext2 2>/dev/null | grep -v '^\(name1\|name2\)\.'
0
27.01.2020, 21:56

Поскольку у вас есть bash, вы можете использовать его расширенное сопоставление шаблонов:

shopt -s extglob
files=( !(name1|name2).@(ext1|ext2) )

Это говорит: все файлы в текущем каталоге, которые не начинаются с "name1" или "name2", за которым следует точка, а затем либо "ext1" или "ext2".

Пример выполнения:

$ touch name1.ext1 name1.ext2 name2.ext1 name2.ext2 name3.ext1 name3.ext2 name3.ext3
$ files=( !(name1|name2).@(ext1|ext2) )
$ declare -p files
declare -a files='([0]="name3.ext1" [1]="name3.ext2")'

Обратите внимание, что если у вас простое имя файла, например "name3.ext2", вам придется выбрать, где поставить точку для сопоставления с образцом - либо в "name3." или в ".ext2"; если у вас более длинные имена файлов, например "name3.intermediate.ext2", то вы можете использовать точки и глобу в середине:

$ files=( !(name1|name2).*.@(ext1|ext2) )
0
27.01.2020, 21:56

Теги

Похожие вопросы