Em find -exec, como substituir o arquivo atual por {}?

Em find -exec, como substituir o arquivo atual por {}?

Quero encontrar todos os arquivos que não são de minha propriedade (ou seja, não tenho permissão para modificá-los). eu tentei

find . -exec if [[ ! -O {} ]]; then echo {}; fi ;

Mas se eu colocar todo o comando -execentre aspas, assim:

find . -exec 'if [[ ! -O {} ]]; then echo {}; fi' \;

Nem isso funciona, porque a referência ao arquivo atual {}está entre aspas e, portanto, não se expande para o arquivo.

O problema é que não sei como incorporar o {}arquivo atual em um arquivo mais complexo -execdo que simplesmente por exemplo find . -exec grep smf {} \;(que usa {}apenas uma vez). Como usar -execa opção find in comandos, onde você faz referência ao arquivo atual mais de uma vez? (Isso está usando {}mais tempo).

Responder1

Seu código não funciona porque o utilitário que você pede findpara executar ifnão existe (é uma palavra-chave na sintaxe do shell).

O -Oteste será verdadeiro se o argumento for um arquivo de propriedade do usuário atual. O mesmo teste pode ser feito sozinho find( -user "$USER"assumindo que $USERse expande para o usuário atual):

find . -type f ! -user "$USER"

Você também pode usar test -Ose o seu utilitário externo testsuportar esse teste não padrão (verifique man test):

find . -type f ! -exec test -O {} \; -print

Se você ainda quisesse ou precisasse usar o -Oteste integrado ao bashshell, seria necessário gerar um bashshell para realizar o teste:

find . -type f -exec bash -c '[[ ! -O "$1" ]]' bash {} \; -print

Isso inicia um bash -cscript embutido para cada arquivo encontrado que executa o teste em seu primeiro argumento ( $1). O argumento é passado na linha de comando do script por find(a bashstring anterior {}será colocada $0dentro do script e será usada por esse shell para mensagens de erro). Se o teste for verdadeiro (o arquivo não pertence a você), -printentra em vigor e imprime o nome do caminho do arquivo.

Você pode fazer isso com um pouco mais de eficiência com

find . -type f -exec bash -c '
    for pathname do
        [[ ! -O "$pathname" ]] && printf "%s\n" "$pathname"
    done' bash {} +

Isso é mais eficiente, pois passa lotes de nomes de caminhos encontrados para o bash -cscript.

... mas usar -user "$USER"seria a melhor opção.

Veja também:

informação relacionada