1

Когда я запускаю find с этими аргументами, он возвращает тысячи файлов:

steven@nook:/mnt/station/media $ sudo find . -not -user steven -or -not -group users | wc
   3508   17479  245851
steven@nook:/mnt/station/media $

Когда я добавляю аргумент -exec , он ведет себя так, как будто find возвращает результатов, а код возврата указывает на успех:

steven@nook:/mnt/station/media $ sudo find . -not -user steven -or -not -group users -exec echo {} \;
steven@nook:/mnt/station/media $ echo $?
0
steven@nook:/mnt/station/media $

(Моя цель - использовать -exec chown -v steven:users {} \; в результатах (следовательно, sudo), но я использую -exec echo {} \; выше, чтобы проиллюстрировать проблему более четко и исключить chown как способствующий фактор.)

Я использую GNU найти под стоковой Баш на Ubuntu Xenial:

steven@nook:/mnt/station/media $ find --version
find (GNU findutils) 4.7.0-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2)
steven@nook:/mnt/station/media $ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
steven@nook:/mnt/station/media $ echo $SHELL
/bin/bash
steven@nook:/mnt/station/media $

2 ответа2

4

Это связано с тем, что смежные операции связываются с подразумеваемым значением -and более жестким, чем явное -or , а также со страницы руководства find(1) : «Если выражение не содержит никаких действий, кроме -prune, -print выполняется для всех файлов, для которых выражение верно ".

Это означает, что find смотрит на выражение в первом примере и видит

(-not -user steven) -or (-not -group users)

и выполняет -print на результат, как вы ожидали.

Find видит ваш второй пример, однако, как

(-not -user steven) -or ((-not -group users) -and -exec echo {})

Это должно отражать все файлы, принадлежащие пользователю steven и не принадлежащие группе пользователей.

Решение состоит в том, чтобы добавить экранированные скобки вокруг выражения перед -exec:

sudo find . \( -not -user steven -or -not -group users \) -exec echo {} \;
1

Вам нужно внести две поправки в вашу командную строку.

Во-первых, скобки команды exec необходимо экранировать или заключать в кавычки, чтобы защитить их от расширения оболочкой. Это прямо упоминается в справочной странице поиска.
На странице руководства также есть пример, поясняющий это требование.

   find . -type f -exec file '{}' \;

   Runs  `file'  on  every file in or below the current directory.  Notice
   that the braces are enclosed in single quote marks to protect them from
   interpretation as shell script punctuation.  The semicolon is similarly
   protected by the use of a backslash, though single  quotes  could  have
   been used in that case also.

Во-вторых, область действия и приоритет выражения -or должны быть разъяснены с помощью круглых скобок (которые также должны быть экранированы).

С исправлениями должно работать следующее:

sudo find . \( -not -user steven -or -not -group users \) -exec echo '{}' \;

Я предпочитаю направлять вывод команды find и использовать xargs, а не синтаксис -exec .

find . -not -user steven -or -not -group users | xargs sudo echo

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .