По крайней мере, в 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 .
С 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)
для включения точечных файлов.
В текущем каталоге вы можете использовать ls
с grep
(при условии, что имена ваших файлов не содержат символов новой строки):
ls -a | grep -E '\.ext(1|2)$' | grep -vE '^name(1|2)\.'
«Только в текущем каталоге» вам не нужно находить
файлы, вы можете просто перечислить их (с обычными оговорками о возможности выявления странных имен файлов, содержащих интересные символы):
ls -d *.ext1 *.ext2 2>/dev/null | grep -v '^\(name1\|name2\)\.'
Поскольку у вас есть 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) )