Como domino o comando find do UNIX?

11

Eu acho que estou bastante avançado no meu uso do find, mas toda vez que eu o uso, não consigo lembrar o método para fechar a opção -exec. Passo bastante tempo lendo cada vez que o uso. Simplesmente não estou usando o suficiente ou esperando muito de mim? Vamos começar com um exemplo típico que me deixa frustrado.

A estrutura de diretórios possui arquivos com todas as permissões incorretas, arquivos ocultos, links simbólicos etc. Desejo alterar a propriedade para um valor razoável

find . -type f -exec chown username {} \;
find . -type d -exec chown username {} \;
find . -type d -exec chgrp usergroup {} \;
find . -type f -exec chgrp usergroup {} \;

(Perdoe-me se o final está ao contrário ... olhei para ele há uma hora e ainda não tenho certeza)

Mas estou com medo de executá-lo por causa de montagens, links simbólicos etc. Fiz a melhor brincadeira com o chmod. * E tive que recorrer a mim antes. Eu sei que o -xdev renunciará ao atravessar partições, mas não tenho certeza do que acontecerá com os arquivos que vivem dentro de diretórios que são links simbólicos.

Então, como alguém domina essa fera que pode matar arquivos cruciais?

Atualize a remoção das melhores sugestões abaixo e o resumo:

  1. Tenha um diretório de prática vinculado e montado em outros diretórios de prática.
  2. Use xargs em vez do comando exec não-intuitivo.
  3. Use -exec echo {} para sanidade e segurança
  4. O ponto e vírgula é especial e você está escapando, portanto o caractere de escape é o primeiro
  5. O comando -or pode ajudá-lo a combinar critérios de seleção.

Estou um pouco confuso com o print0, mas o xargs sempre foi um pouco difícil de entender, à primeira vista, na prática que tento evitar.

ojblass
fonte
1
Também não me lembro, então apenas coloco em xargs.
Resonator
2
Quando estiver satisfeito com a criação do comando certo, considere executá-lo com + em vez de \; Ele será executado mais rapidamente com + porque o comando exec será chamado com muito menos frequência.
wzzrd 22/06/2009
wzzrd, ótima dica sobre o uso de + em vez de \;
22411 Daniel Lawson

Respostas:

19

Bem, no que diz respeito à -execsintaxe, você pode gostar de muitas pessoas, desistir e usar xargs:

find . -type f | xargs chown username

(ou a versão arquivos com espaços e outras bobagens-neles-seguras)

find . -type f -print0 | xargs -0 chown username

Ou, para tentar se lembrar da coisa certa a fazer com o ponto-e-vírgula, o que você precisa detalhar é que você está usando um ponto-e-vírgula para finalizar o comando que -execestá sendo executado e você precisa escapar do ponto-e-vírgula porque possui significado para bash. É por isso que é ponto e vírgula com barra invertida. Você parece ter a {}parte de substituição correta.

Quanto a matar arquivos e assim por diante, se você estiver executando algo grande e perigoso como o que está falando, primeiro faça o seguinte:

find . -type f -exec echo chown username {} \;

e revise os resultados. Isso é basicamente uma "execução a seco", na qual você vê os comandos que seriam executados se você deixasse. Definitivamente uma boa prática. Não vai ajudar com o .*problema, mas você sabe que não deve fazer isso agora. :)

caos
fonte
1
+! para o 'eco', pratique corrida a seco. Eu sempre usar isso para uma grande mudança
Steve Folly
3

Estou surpreso que ninguém ainda tenha mencionado a seguinte opção:

find . -type f -ok chown username {} \;

Essa sintaxe confirmará o comando antes de executá-lo. Funciona melhor se você espera que sua correspondência seja um número relativamente pequeno de arquivos, porque será solicitado um para cada um.

Algumas respostas mencionam xargs, mas com o GNU acham que isso também é desnecessário:

find . -type f -exec chown username {} \+

Observe que o + normalmente não precisa ser escapado, mas é bom adquirir o hábito de fazê-lo de qualquer maneira.

Kamil Kisiel
fonte
Você pode explicar a natureza do sinal de mais ... o que exatamente ele está fazendo? O shell está processando isso ou o comando. Eu acho que vou baixar o código fonte do gnu-find porque este é um tópico interessante.
ojblass
find está processando-o. Leia man find para descobrir mais sobre essa opção.
276 Kamil Kisiel
3

É para isso que o homem serve: Pode ser difícil lembrar de coisas, é por isso que o comando * nix inclui páginas de manual. Você pode apenas verificar sempre a seção de ação da página do homem para um lembrete sobre a sintaxe: man find. Embora as páginas de manual possam parecer pouco amigáveis, uma vez que você é bom em lê-las, elas são muito úteis.

Crie um Front-End ou Wrapper: Quando quis melhorar o GNU find, escrevi um front end da GUI para o find que gera comandos find com python, glade e pygtk. Este é um bom exercício se você quiser conhecê-lo muito bem.

Tenha um diretório de prática: Por fim, eu sempre tenho um diretório 'scrap' no meu diretório home para tocar com comandos poderosos quando algo como 'eco' não é suficiente. Você pode usar a expansão do shell para criar rapidamente um monte de arquivos com algo como:

for i in {1..100}; do touch "$i"; done
Kyle Brandt
fonte
Um diretório de prática estranho é algo que nunca considerei.
ojblass
1

Você também pode combinar expressões de localização com operadores '- e' e '- ou'. -e está implícito:

find . -type f -name "plainfile" ...

é o mesmo que

find . -type f -and -name "plainfile" ...

O operador or pode reduzir sua lista de 4 comandos para 2:

find . -type d -or -type f ...

E, finalmente, não relacionado a encontrar, mas o chown também pode definir o grupo. Então, lidando com espaços nos nomes, acabamos com:

find . -type d -or -type f -exec chown username:usergroup '{}' \;
Steve Folly
fonte
O que encontrar com o -ou negócios. [Sic] #
ojblass 29/06/2009
@ojblass: find combina expressões usando 'e' ou 'ou', por padrão, se nem '-and' nem '-or' forem especificados, '-and' será usado implicitamente. Portanto, digite 'find -type d -type f' não encontrará nada porque nada é um diretório e um arquivo.
Steve Folly
0

Ao fechar, apenas penso em usar; como em muitas linguagens de programação e depois escapando. Lembre-se de que é preciso escapar e isso chega a você com bastante facilidade.

Garry Harthill
fonte
0

Dependendo da versão do achado que você está usando, existem diferentes opções que podem ajudá-lo. A descoberta do GNU é provavelmente a mais poderosa e isso pode ajudá-lo com sua segunda pergunta (implícita)

Por exemplo - o comportamento padrão não é desreferenciar links simbólicos, mas você pode substituí-lo; e a opção -mount para encontrar os pontos de montagem

Procure nas páginas de manual locais


fonte
0

Alguns argumentam que a opção xargs é mais rápida que a opção -exec, porque não executará o comando uma vez para cada arquivo, mas eu não me preocuparia com nada, exceto trabalhos maciços que demoram um tempo não trivial.

Pessoalmente, eu normalmente apenas executo find sem exec

find /path/to/dir -name whatever

verifique se a saída parece correta e execute meu comando nessa lista.

chown user:group `find /path/to/dir -name whatever`
theotherreceive
fonte
Exemplo perfeito de como "não" fazer as coisas. Nomes de arquivos com espaços.
Ian Kelling
Sim, esse é um problema em potencial que eu talvez devesse ter reconhecido. No entanto, meu objetivo era ler a saída de localização antes de executar qualquer coisa, onde você identificaria espaços ou outra loucura de nome de arquivo.
theotherreceive
0

Em algumas conchas (não no bash), escape {} para um comportamento adequado.

\{\} or '{}'

O manual find é bom para dominar o find.

Ian Kelling
fonte
Não, você não faz; find funciona perfeitamente com o {} como está. Eles fazem parte do comando find: são um token que é substituído pelo resultado do comando find. Eles significam apenas algo no bash ao definir funções ou chamar variáveis, para que você possa usá-las como na pergunta original.
Wzzrd 22/06/2009
É da página de manual. Eu atualizei para dizer que não é aplicável ao bash.
22610 Ian Kelling
0

Antes de fazer algo assim, verifique se o diretório em que este comando está sendo executado não está no mesmo sistema de arquivos que / usr ou / etc. (caso contrário, se eu tiver um link físico para / etc / passwd ou / bin / sh no meu diretório pessoal, você acabou de me dar posse desses e, como efeito colateral, agora possuo a máquina).

Se você deseja recursar através de um diretório e exibir todos os arquivos / diretórios, um simples

chown -Rh user: usergroup user /

vai fazer isso. Certifique- se de usar o -h ou o chown seguirá os links simbólicos.

chris
fonte
Eu não acho que isso seja multiplataforma. Também falha com 247K de arquivos, conforme demonstrado pelo meu ambiente de prática. Não sei por quê.
ojblass
Acho que você encontrou um bug mais do que um problema de plataforma cruzada. Qual versão e qual é o status de saída quando falha? Tanto quanto posso dizer, ele se originou nas primeiras versões do bsd; é definitivamente em sunos 5.3 e ultrix e irix. Quantos processam antes de falhar?
chris
Você está certo de que funciona nas distribuições do AIX 5.3, AIX 5.2, mas não do AIX 4.3, NCR, HP 11, HP 10.20 ou minhas DSL. Em todos os casos, parece falhar em arquivos de 60k ou próximos a ele.
ojblass