Como excluir / ignorar arquivos e diretórios ocultos em uma pesquisa "encontrar" incorporada com curinga?

119

A partir de (observe os caracteres curinga antes e depois de "algum texto")

find . -type f -name '*some text*'

como excluir / ignorar todos os arquivos e diretórios ocultos?

Eu já estou pesquisando há muito tempo , me deparei com alguns - podar e! (ponto de exclamação), mas nenhum exemplo apropriado (e parcimonioso) que funcionou .

Tubulação | para grepseria uma opção e eu também gostaria de receber exemplos disso; mas, principalmente , estou interessado em uma única linha (ou duas linhas independentes, ilustrando maneiras diferentes de atingir o mesmo objetivo de linha de comando) que apenas estou usando find.

ps: Localizar arquivos no linux e excluir diretórios específicos parece intimamente relacionado, mas a) ainda não foi aceito eb) está relacionado, mas é diferente e distinto, mas c) pode fornecer inspiração e ajudar a identificar a confusão!

Editar

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", trabalho. O regex procura por "qualquer coisa, depois uma barra, depois um ponto e depois qualquer coisa" (ou seja, todos os arquivos e pastas ocultos, incluindo suas subpastas) e o "!" nega o regex.

noz sobre natty
fonte
Não ajuda com o que você pediu na sua edição, mas dê uma olhada na minha pergunta e sua resposta aqui: unix.stackexchange.com/q/69164/15760 e também no link da resposta.

Respostas:

134

Isso imprime todos os arquivos que são descendentes do seu diretório, pulando arquivos e diretórios ocultos:

find . -not -path '*/\.*'

Portanto, se você estiver procurando por um arquivo com some textseu nome e quiser pular arquivos e diretórios ocultos, execute:

find . -not -path '*/\.*' -type f -name '*some text*'

Explicação:

A -pathopção executa verifica um padrão em toda a cadeia de caminho. *é um curinga, /é um separador de diretório, \.é um ponto (ele precisa ser escapado para evitar um significado especial) e *é outro curinga. -notsignifica não selecionar arquivos que correspondam a este teste.

Eu não acho que findseja inteligente o suficiente para evitar a pesquisa recursiva de diretórios ocultos no comando anterior; portanto, se você precisar de velocidade, use o -pruneseguinte:

 find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*some text*' -print
Flimm
fonte
Note com o último que você precisa -printno final! Além disso, não tenho certeza se -name '\.*' would be more efficient instead of -path` (porque o caminho é pesquisar subcaminhos, mas estes serão podadas para fora)
artfulrobot
Qual é o significado especial .desse contexto?
frostschutz
@frostschutz O ponto depois findsignifica o diretório atual: findexaminará todos os arquivos e diretórios no diretório atual. O argumento a seguir pathé uma expressão regular, em que um ponto normalmente significa "qualquer caractere". Para fazer com que ele signifique um ponto literal, precisamos escapar com uma barra invertida. O argumento depois -name não é uma expressão regular, mas expande curingas como ?e *como um shell.
Flimm
2
@frostschutz Na verdade, pense bem, posso estar errado em .ter um significado especial.
Flimm
11
@ Simlim, não há necessidade de escapar .. Tanto quanto eu estou ciente, apenas estes devem ser precedidos: *, ?, e [].
thdoan
10

Este é um dos poucos meios de excluir arquivos de ponto que também funcionam corretamente no BSD, Mac e Linux:

find "$PWD" -name ".*" -prune -o -print
  • $PWD imprima o caminho completo no diretório atual para que o caminho não comece com ./
  • -name ".*" -prune corresponde a qualquer arquivo ou diretório que comece com um ponto e não desça
  • -o -printsignifica imprimir o nome do arquivo se a expressão anterior não corresponder a nada. Usar -printou -print0faz com que todas as outras expressões não sejam impressas por padrão.
eradman
fonte
Por favor, explique / elabore sobre "alarmantemente complicado"; as respostas já dadas e sua resposta parecem evidenciar o contrário ...?
noz sobre natty
2
"assustadoramente complicado" é provavelmente excessivo. Eu reformulei a resposta para chegar ao ponto. Acho que a resposta que postei é difícil de entender e difícil de ver sem uma leitura muito cuidadosa da página de manual. Se você estiver usando apenas o GNU find, existem mais soluções possíveis.
eradman
-o ... -printé útil. Para meu uso, agora tenho find ... '!' -name . -name '.*' -prune -o ... -print, o que era mais conveniente do que incluir $ PWD.
Roger Pate
4
find $DIR -not -path '*/\.*' -type f \( ! -iname ".*" \)

Exclui todos os diretórios ocultos e arquivos ocultos em $ DIR

convidado
fonte
Esta é a resposta perfeita. Ele encontra recursivamente todos os arquivos, mas exclui itens de linha para diretórios e arquivos ocultos. Obrigado!
precisa saber é o seguinte
2

A resposta que originalmente publiquei como uma "edição" para minha pergunta original acima:

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", trabalho. O regex procura por "qualquer coisa, depois uma barra, depois um ponto e depois qualquer coisa" (ou seja, todos os arquivos e pastas ocultos, incluindo suas subpastas) e o "!" nega o regex.

noz sobre natty
fonte
Semelhante, mas apenas para a pasta atual:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
phyatt 22/03
2

Você não precisa usar findpara isso. Basta usar o globstar no shell ele mesmo, como:

echo **/*foo*

ou:

ls **/*foo*

onde **/representa qualquer pasta recursivamente e *foo*qualquer arquivo que tenha fooseu nome.

Por padrão, o uso lsimprimirá nomes de arquivos, excluindo arquivos e diretórios ocultos.

Se você não tem o globbing ativado, faça isso por shopt -s globstar.

Nota: Uma nova opção de globbing funciona no Bash 4, zsh e shells semelhantes.


Exemplo:

$ mkdir -vp a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'
$ touch a/b/c/d/foo a/b/c/d/bar  a/b/c/d/.foo_hidden a/b/c/d/foo_not_hidden
$ echo **/*foo*
a/b/c/d/foo  a/b/c/d/foo_not_hidden
kenorb
fonte
5
Você não precisa lsdisso! echo **/*foo*
Kevin Cox
@kenorb (e @ kevin-cox). Você poderia ser um pouco mais detalhado? Por que a globstar (= *) funcionaria aqui e como? O que a barra / faz?
Noz sobre natty
@nuttyaboutnatty /significa pasta, separa os diretórios do nome do arquivo. *basicamente representa tudo.
Kenorb 18/05
@kenorb yes-but: como essa one-liner ajuda na pergunta original?
Noz sobre natty
11
@nuttyaboutnatty Exemplo esclarecido e adicionado. Ajuda encontrando arquivos ignorando o oculto.
Kenorb 19/05
1

A resposta do @ Flimm é boa, principalmente porque impede que a busca desça para diretórios ocultos . Eu prefiro esta simplificação:

Geralmente para excluir todos os caminhos ocultos (arquivos regulares, diretórios etc.):

find <start-point> -path '*/.*' -prune -o <expression> -print

Por exemplo, usando seu diretório de trabalho como ponto de partida e -name '*some text*'como a expressão:

find . -path '*/.*' -prune -o -name '*some text*' -print

Em contraste com o que a resposta de @ Flimm sugere, nenhum arquivo ou diretório oculto é o caso simples. A -path '*/.*'expressão é verdadeira para qualquer caminho (arquivos regulares, diretórios, etc) que tenha um .imediatamente após o separador de arquivos /,. Portanto, essa linha remove arquivos e diretórios ocultos.

Permitir arquivos ocultos enquanto exclui diretórios ocultos é o caso que requer um filtro adicional. É aqui que você incluiria -type dna expressão sendo removida.

find <start-point> -type d -path '*/.*' -prune -o <expression> -print 

Por exemplo:

find . -type d -path '*/.*' -prune -o -name '*some text*' -print

Nesse caso, -type d -path '*/.*'é trueapenas para diretórios e, portanto, apenas os diretórios são removidos.

De novo
fonte
0

findpossui opções lógicas simples, como -ande -notvocê pode usá-las para sua vantagem, para encontrar um arquivo correspondente com duas regras como esta:

$ touch non_hidden_file.txt .hidden_file.txt somethings/.another_hidden_file.txt                                                 

$ find . -type f -name '*hidden_file*' -and \( -not -name ".*" \)                            
./non_hidden_file.txt

Como você pode ver, findusa duas regras -name '*hidden_file*'e -and \( -not -name ".*" \)encontra os nomes de arquivos que correspondem às duas condições - o nome do arquivo hidden_file, mas sem o ponto inicial. Observe as barras na frente de parênteses - elas são usadas para definir parênteses como findargumentos, em vez de definir um subshell (que é o que parênteses significa de outra forma sem barras)

Sergiy Kolodyazhnyy
fonte
0
$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Notas:

  • . : pasta atual
  • remover -maxdepth 1para pesquisar recursivamente
  • -type f: encontre arquivos, não diretórios ( d)
  • -not -path '*/\.*' : não retorne .hidden_files
  • sed 's/^\.\///g': remova o anexo ./da lista de resultados
Victoria Stuart
fonte