Существует более одного разумного толкования этого вопроса - см. Ниже ответ, основанный на другом ответе.
Предполагается, что вы имеете в виду критерии "Любой" ...
Рассмотрим следующую настройку:
files_empty=(
SESS/log_snap_1234 # ignored because not more than 1k in size
SESS/ignoreme # ignored because not matching either pattern
SESS/core.13.gz # expected to be in results
SESS/core.13 # expected to be in results
)
files_full=(
SESS/log_snap_2345 # expected to be in results
)
{ tempdir=$(mktemp -d /tmp/test.XXXXXX) && cd "$tempdir"; } || exit
mkdir -p SESS bad
touch "${files_empty[@]}"
for f in "${files_full[@]}"; do
dd if=/dev/zero of="$f" bs=1k count=2
done
Если после использования вышеописанного для создания тестовой среды мы запустим в GNU find
следующее:
find ./SESS \
'(' '(' -name 'log_snap_*' -size +1k ')' \
-o '(' -regextype posix-extended -regex ".*core[.][0-9]+([.]gz)?" ')' \
')' -print
... мы правильнополучить результаты:
./SESS/log_snap_2345
./SESS/core.13
./SESS/core.13.gz
Итак, что изменилось?
- Не использовать
-path
для фильтрации искомых мест, когда вы можете просто изменить начальныйместа вместо.Когда вы запускаете find . -path './SESS/*'
, он ищет везде по .
, но затем выбрасывает результаты, когда они не соответствуют ./SESS/*
;это крайне неэффективно по сравнению с поиском только нужных вам каталогов. - Используйте
-o
, чтобы указать условие ИЛИ. - Нет смысла группировать операторы или явно
-a
когда между последующими тестами требуется AND, поскольку это неявное поведение. - Задание конечного действия (например,
-print
) в явном виде - очень хорошая форма.Не совсем обязательно в вашей текущей ситуации, но является обязательным в других распространенных сценариях (например, при использовании -prune
);таким образом, создание привычки уменьшает пространство для ошибок. - Регулярному выражению запрещено начинать с
*
, поскольку *
означает «ноль или более предыдущего элемента».В начале регулярного выражения отсутствует предшествующий элемент, поэтому эта конструкция не имеет значения. - Внутри регулярного выражения явный период должен быть записан как
[.]
, так как пустой.
означает «один из любых символов».
Если вы действительно имеете в виду «оба» критерия ...
На самом деле нам не нужно углубляться в find
за эту часть.Одно предостережение: я сознательно избегаю правильной обработки случая, когда имена файлов содержат буквальные переводы строк.Это может случитьсяИгнорировать это не идеально.
Во всяком случае, возьмите две функции оболочки в качестве резервных для вывода двух разных команд find
:
find1_cmd() {
printf '%s\n' \
SESS/session_one/log_snap_1234 \
SESS/session_one/log_snap_4567 \
SESS/session_three/log_snap_8901
}
find2_cmd() {
printf '%s\n' \
SESS/session_one/core.1234.gz
SESS/session_four/core.5678.gz
}
Мы можем найти только каталогиприсутствует в обоих случаях следующим образом:
prep() {
while IFS= read -r line; do
printf '%s\n' "${line%/*}" # remove the filename, leaving only the directory
done | sort -u # sort and uniq-ify the results
}
comm -12 <(find1_cmd | prep) <(find2_cmd | prep)
Конечно, вы можете заменить цикл while
любым другим способом удаления имени файла и оставления только каталога.Важно то, что мы (1) генерируем отсортированный список уникальных каталогов, найденных каждой командой;и (2) использование comm
для исключения каталогов, уникальных для одного или другого.
См. BashFAQ # 36 , чтобы узнать больше об использовании comm
.