Diferença entre ponto e asterisco no comando find

1

Eu tenho um Synology NAS, que usa um Linux personalizado para seu sistema operacional. Usando o comando find , estou tentando listar os arquivos modificados desde cerca de 25 dias, com algumas exclusões, dentro de um diretório específico.

Eu notei que quando eu uso um "*" em vez de um "." depois de find , o resultado parece diferente. Veja os comandos abaixo:

find . ! -path "*@eaDir*" -type f ! -iname ".DS_Store" ! -iname "Thumbs.db" -mtime -25

find * ! -path "*@eaDir*" -type f ! -iname ".DS_Store" ! -iname "Thumbs.db" -mtime -25

Quando utilizei um ".", obtive alguma saída após um longo período de tempo. Quando eu substituí o "." por um "*", comecei a obter mais resultados muito rapidamente e eles eram diferentes do que quando se usava um ".".

Eu usei ls -al para verificar se os resultados ao usar um "*" estavam corretos, ou seja, se a data / hora modificada dos arquivos estava nos últimos 25 dias e, de fato, esse foi o caso.

Alguém pode me dizer por que os resultados são diferentes?

    
por EEM RT 27.02.2017 / 16:25

2 respostas

1

O ponto significa o diretório atual. É comum usá-lo como o PATH inicial para find .

O asterisco simples será expandido pelo shell antes que find seja executado no conteúdo do diretório atual. Isso é chamado de "globbing". Para ver o efeito, faça:

echo *

Sem dúvida, find * ... não é o que você deseja usar.

    
por 27.02.2017 / 16:34
1

Em:

find * ...

como uma linha de comando do shell, * é um glob que é expandido pelo shell para a lista (lexicamente ordenada) de entradas não ocultas no diretório atual (com alguns shells, que seriam apenas as entradas que contêm somente caracteres válidos como * como um padrão significam 0 ou mais caracteres ).

Assim, se o diretório atual contiver essas entradas:

  • .
  • ..
  • .htaccess
  • file.txt
  • -foo-

find será chamado com esses argumentos: find , -foo- , file.txt (e ... ). find provavelmente se queixará do -foo- que é uma opção ou predicado inválido.

Mesmo se você usar:

find -- * ...

Isso não funcionará corretamente para arquivos com o nome -anything ou ! ou ( ..., pois -- informará apenas find para parar de procurar opções (como -L , -H ) não para predicados.

Você pode usar:

find ./* ...

para evitar os problemas, mas, novamente, omitir arquivos ocultos, omitir arquivos com caracteres inválidos ou quebrar (com lista de argumentos muito longa ) se houver muitos arquivos no arquivo atual diretório.

Com:

find . ...

Você só passa . para find . . é o diretório atual. Então, é find , não o shell que procurará arquivos lá (inclui . na profundidade 0, todas as entradas exceto . e .. (outras entradas ocultas incluídas) na profundidade 1 e todas as outras entradas para subdiretórios (ainda excluindo . e .. ) de forma recursiva.

Você só deseja usar:

find ./* ...

Se você quiser que a lista de arquivos na profundidade 1 (e profundidade 1 somente) seja classificada e queira excluir arquivos ocultos na profundidade 1 (e novamente na profundidade 1 somente). O que seria muito improvável.

Se você quiser excluir arquivos ocultos, adicione um ! -name '.*' ou -name '[!.]*' (embora tenha cuidado com nomes de arquivos com caracteres inválidos, e isso também incluirá o diretório de nível superior dado a find . , que acontece com coincidir com esse padrão).

Se você quisesse classificar em todos os níveis, provavelmente desejaria recorrer a zsh e a sua globalização recursiva com qualificadores glob.

O motivo pelo qual você está obtendo resultados diferentes é muito provavelmente que, em find * , o find comece procurando (está sendo instruído a procurar) no primeiro arquivo ou diretório no diretório atual em ordem alfabética , e com find . , olha para . em si, mas depois o primeiro arquivo ou diretório lá em uma ordem diferente (pode ser a ordem em que as entradas são armazenadas no diretório, mas algumas find implementations também classificam a lista pelo número do inode como uma tentativa de minimizar as buscas na cabeça do disco).

BTW, a melhor maneira de escrever seu comando provavelmente seria:

find . \( -name @eaDir -o -iname .DS_Store -o -iname Thumbs.db \) \
  -prune -o -mtime -25 -type f -print

Isso indica ao find para ignorar esses diretórios e seu conteúdo (nem mesmo tentar olhar dentro deles).

    
por 27.02.2017 / 16:53

Tags