Eu queria executar recursivamente chmod go+w
em uma pasta específica, incluindo arquivos ocultos, e primeiro tentei
find . -name ".*" -o -name "*" -exec chmod go+w {} \;
mas descobri que isso não estava afetando os arquivos ocultos. Para me verificar, corri apenas
find . -name ".*" -o -name "*"
e os arquivos ocultos foram listados. Também notei que se eu excluísse a -o -name "*"
parte, ele faria chmod nos arquivos ocultos (mas excluiria os não ocultos, é claro). Minha última tentativa foi usar xargs
find . -name ".*" -o -name "*" | xargs chmod go+w
que finalmente funcionou como esperado. O que estou fazendo de errado no primeiro trecho?
Servidor Red Hat Enterprise Linux versão 6.8 (Santiago)
GNU bash, versão 4.3.42(1)-release (x86_64-unknown-linux-gnu)
Responder1
A solução é vincular os dois testes de nome com parênteses.
Para ilustrar isso, vamos considerar um diretório com três arquivos regulares:
$ ls -a
. .. .hidden1 .hidden2 not_hidden
Agora, vamos ao comando original:
$ find . -name ".*" -o -name "*" -exec echo Found {} \;
Found ./not_hidden
Somente o arquivo não oculto é encontrado.
A seguir, vamos adicionar parênteses para agrupar os dois testes de nome:
$ find . \( -name ".*" -o -name "*" \) -exec echo Found {} \;
Found .
Found ./not_hidden
Found ./.hidden1
Found ./.hidden2
Todos os arquivos foram encontrados.
A solução é usar parênteses.
Mais detalhes
No comando original, não há operador entre -name "*"
e -exec ... \;
. Conseqüentemente, find
assume o operador padrão que é lógico e. Como a ligação lógica-e é mais rígida que a lógica-ou ( -o
), isso significa que o comando é interpretado como:
find . \( -name ".*" \) -o \( -name "*" -exec echo Found {} \; \)
Isso significa que exec
será executado somente se a primeira name
condição não corresponder.
Para obter mais informações, consulte oOPERADORESseção em man find
.
O que acontece sem-exec
Vamos tentar usar um simples -print
:
$ find . -name ".*" -o -name "*" -print
./not_hidden
Como você pode ver, -print
vinculado ao -name "*"
com o lógico implícito e como acima.
Mas considere o que acontece sem nenhuma ação especificada:
$ find . -name ".*" -o -name "*"
.
./not_hidden
./.hidden1
./.hidden2
Aqui, todos os arquivos foram encontrados. A razão é que, nesta versão, -o
é oapenasoperador.