'find' não retorna nenhum resultado ao adicionar -exec

1

Quando executo find com esses argumentos, ele retorna milhares de arquivos:

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

Quando eu adiciono um argumento -exec , ele se comporta como se find não retornasse nenhum resultado e o código de retorno indicasse sucesso:

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 $

(Meu objetivo é usar -exec chown -v steven:users {} \; nos resultados (daí sudo ), mas estou usando -exec echo {} \; acima para ilustrar o problema com mais clareza e descartar chown como um fator contribuinte.)

Estou usando o gnu no bash do 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 $
    
por Steven K 04.06.2017 / 00:49

2 respostas

4

Isso ocorre porque as operações adjacentes vinculam-se a um -and implícito que é o -or explícito e porque, a partir da página find(1) man, "se a expressão não contiver ações diferentes de -prune, -print será executada todos os arquivos para os quais a expressão é verdadeira. "

Isso significa que find olha a expressão em seu primeiro exemplo e vê

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

e realiza -print no resultado, como você esperava.

Find vê seu segundo exemplo, no entanto,

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

Isso deve ecoar todos os arquivos pertencentes ao usuário steven e não pertencentes a usuários do grupo.

A solução é adicionar parênteses com escape em torno da sua expressão antes do -exec :

sudo find . \( -not -user steven -or -not -group users \) -exec echo {} \;
    
por 04.06.2017 / 02:42
1

Você precisa fazer duas correções na sua linha de comando.

Primeiro, as chaves do comando exec precisam ser escapadas ou citadas para protegê-las da expansão pelo shell. Isso é explicitamente mencionado na página do manual find .
Há também um exemplo na página man para esclarecer este requisito.

   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.

Em segundo lugar, o escopo & A precedência da expressão -or precisa ser esclarecida com parênteses (que também precisam ser escapados).

Com as correções, o seguinte deve funcionar:

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

FWIW Eu prefiro canalizar a saída do comando find e usar xargs em vez de lidar com a sintaxe de -exec .

find . -not -user steven -or -not -group users | xargs sudo echo
    
por 04.06.2017 / 02:21