find: lista todos os diretórios, exceto aqueles com números em seus nomes e seus filhos

6

Estou executando o seguinte para encontrar todos os diretórios sem um número neles (sem incluir o caminho original):

find /path/2/directory -type d -name '[!0-9]*'

O problema é que ele encontra diretórios que são subdiretórios de diretórios com números.

Exemplo:

/path/2/directory/20160303/backup

ou até mesmo

/path/2/directory/backup20160303a/backup

Existe alguma maneira de impedir que a busca retorne tais diretórios?

Não consigo resolver este problema limitando a profundidade, a profundidade pode variar.

Exemplo:

/path/2/directory/subdirectory/20160303/backup
    
por Mocking 03.03.2016 / 23:29

4 respostas

10

Use -prune para ignorar esses diretórios:

find /path/to/directory -name '*[0-9]*' -prune -o -type d -print

no entanto, se você estiver em um gnu setup, talvez queira usar o C locale ao executar o acima, veja o comentário do Stéphane abaixo.

    
por 03.03.2016 / 23:57
5

Se você não quiser encontrar descida além de uma certa correspondência, use -prune e não, por exemplo. -path ou filtrando a saída de find com grep -v

Para testar as coisas, crie um ambiente com alguns arquivos e subdiretórios extras, para que você possa verificar o find para não exibir material indesejado:

mkdir -p tmp/2/abc/def
touch tmp/2/abc/def/file1
mkdir -p tmp/2/abc/9876/xyz
touch tmp/2/abc/9876/xyz/file2
tree tmp/

dá:

tmp
└── 2
    └── abc
        ├── 9876
        │   └── xyz
        │       └── file2
        └── def
            └── file1

Se você usar find tmp/2/abc \! -path "*[0-9]*" como sugerido por @terdon, a saída estará vazia, porque -path não leva em conta apenas os diretórios que começam abaixo de abc , mas o caminho completo, que inclui 2 . Então não é isso que você quer.

Se você usar find tmp/2/abc -type d | grep -vE '/[0-9-]+(/|$)' , como sugerido pelo @cas, você verá que ele também não imprime nada, mais uma vez porque ele corresponde não apenas aos arquivos abaixo de onde você está pesquisando, mas também ao diretório denominado% código%. Além disso, isso exigiria que primeiro percorresse a árvore inteira sob 2 e se houvesse algumas centenas de milhares de itens, a caminhada (e a filtragem) levaria uma quantidade considerável de tempo.

Se você fizer isso:

find tmp/2/abc -type d -name '[!0-9]*' -print 

você verá que a saída inclui o caminho 9876 . Para obter livra-se daquilo que você não quer com tmp/2/abc/9876/xyz :

find tmp/2/abc -type d -name '[!0-9]*' -print -o -name '[0-9]*' -prune

que dá:

tmp/2/abc
tmp/2/abc/def

você pode melhorar um pouco a eficiência disso trocando a poda e imprimindo, o que foi feito por @don_cristti em seu aprimoramento desta resposta.

    
por 03.03.2016 / 23:39
2

Acho que você está procurando -path :

   -path pattern
          File  name matches shell pattern pattern.  The metacharacters do
          not treat '/' or '.' specially; so, for example,
                    find . -path "./sr*sc"
          will print an entry for a directory called './src/misc' (if  one
          exists).  

Ele procura o caminho inteiro de cada arquivo / diretório para o padrão fornecido. Então, se você tem uma estrutura de diretórios como esta:

$ tree
.
├── 111
│   └── foo
│       └── bar
├── bar
│   └── foo
│       └── baz
└── foo
    └── 111
        └── bar

9 directories, 0 files

Você pode usar find da seguinte forma:

$ find /path/to/directory/ \! -path "*[0-9]*" 
.
./foo
./bar
./bar/foo
./bar/foo/baz

Ou com o GNU find :

find /path/to/directory/ -not -path "*[0-9]*" 

Como isso terá que descer em cada diretório para verificar seu nome, ele será significativamente mais lento em grandes árvores de diretórios do que @ Solução de Anthon com ameixa seca. Se você não tem milhares de diretórios, tudo bem.

    
por 03.03.2016 / 23:45
0

É fácil usar grep (ou awk ou sed ou perl etc) para remover esses diretórios da saída de find :

find /path/to/directory -type d | grep -vE '/[0-9-]+(/|$)'

Nota: Incluí - na classe de caracteres porque os diretórios com datas são às vezes YYYY-MM-DD em vez de apenas AAAAMMDD

    
por 03.03.2016 / 23:44