Encontre uma lista de diretórios um nível abaixo do diretório correspondente

10

Estou tentando obter uma lista de diretórios contidos em uma pasta específica.

Dadas estas pastas de exemplo:

foo/bar/test
foo/bar/test/css
foo/bar/wp-content/plugins/XYZ
foo/bar/wp-content/plugins/XYZ/js
foo/bar/wp-content/plugins/XYZ/css
baz/wp-content/plugins/ABC
baz/wp-content/plugins/ABC/inc
baz/wp-content/plugins/ABC/inc/lib
baz/wp-content/plugins/DEF
bat/bar/foo/blog/wp-content/plugins/GHI

Gostaria que um comando retornasse:

XYZ
ABC
DEF
GHI

Essencialmente, estou procurando as pastas que estão dentro do wp-content / plugins /

Usar find ficou mais próximo de mim, mas não posso usar -maxdepth , porque a pasta está muito longe de onde estou procurando.

A execução do seguinte retorna todos os diretórios filhos, de forma recursiva.

find -type d -path *wp-content/plugins/*

foo/bar/wp-content/plugins/XYZ
foo/bar/wp-content/plugins/XYZ/js
foo/bar/wp-content/plugins/XYZ/css
baz/wp-content/plugins/ABC
baz/wp-content/plugins/ABC/inc
baz/wp-content/plugins/ABC/inc/lib
baz/wp-content/plugins/DEF
bat/bar/foo/blog/wp-content/plugins/GHI
    
por Nick 27.02.2017 / 22:14

7 respostas

12

Basta adicionar um -prune para que os diretórios encontrados não sejam inseridos em:

find . -type d -path '*/wp-content/plugins/*' -prune -print

Você precisa citar o *wp-content/plugins/* como também é um shell glob.

Se você quiser apenas os nomes dos diretórios em oposição ao caminho completo, com GNU find , você pode substituir o -print por -printf '%f\n' ou assumindo que os caminhos de arquivo não contêm caracteres de nova linha, canalizar a saída de o comando acima para awk -F / '{print $NF}' ou sed 's|.*/||' (também assumindo que os caminhos de arquivo contêm apenas caracteres válidos).

com zsh :

printf '%s\n' **/wp-content/plugins/*(D/:t)

**/ é qualquer nível de subdiretórios (recurso originado em zsh nos primeiros nighties e agora encontrado na maioria dos outros shells como ksh93 , tcsh , fish , bash , yash embora geralmente sob alguma opção), (/) para selecionar apenas arquivos do tipo diretório , D para incluir os ocultos (ponto), :t para obter o final (nome do arquivo).

    
por 27.02.2017 / 22:45
4

Bash-ically:

shopt -s globstar
printf "%s\n" **/wp-content/plugins/*

impressões:

bat/bar/foo/blog/wp-content/plugins/GHI
baz/wp-content/plugins/ABC
baz/wp-content/plugins/DEF
foo/bar/wp-content/plugins/XYZ

ou

shopt -s globstar
for d in **/wp-content/plugins/*; do printf "%s\n" ${d##*/}; done

impressões:

GHI
ABC
DEF
XYZ
    
por 27.02.2017 / 22:33
4

Você pode ter find recurse, mais ou menos:

find / -type d -path *wp-content/plugins -exec find {} -maxdepth 1 -mindepth 1 -type d \;
    
por 27.02.2017 / 22:18
3

Para Bash: Simples (funciona para arquivos / diretórios com espaços e novas linhas ):

shopt -s globstar                    # allow ** for several dirs.
a=(**/wp-content/plugins/*/)         # capture only wanted dirs.
a=("${a[@]%/}")                      # remove trailing slash (dirs) '/'.
printf '%s\n' "${a[@]##*/}"          # print only the last dir name.

Imprimiremos:

GHI
ABC
DEF
XYZ

Mesmo se houver arquivos criados.

    
por 28.02.2017 / 13:59
3

O comando tree é projetado exatamente para essa finalidade. A profundidade pode ser controlada com o sinalizador -L . Aqui está um exemplo em um site Wordpress local que eu mantenho:

$ tree -L 1 wp-content/
wp-content/
├── index.php
├── plugins
└── themes

2 directories, 1 file

$ tree -L 2 wp-content/
wp-content/
├── index.php
├── plugins
│   ├── akismet
│   ├── contact-form-7
│   ├── index.php
│   └── wordpress-seo
└── themes
    ├── index.php
    ├── twentyfifteen
    └── twentysixteen

11 directories, 3 files

$ tree -L 1 wp-content/plugins/
wp-content/plugins/
├── akismet
├── contact-form-7
├── index.php
└── wordpress-seo

5 directories, 1 file
    
por 28.02.2017 / 13:53
1

Com base na resposta do DopeGhoti, que tal o loop de correspondência:

find / -type d -iregex '.*/wp-content/plugins' -print0 | while read -r -d $'
find / -type d -iregex '.*/wp-content/plugins' -print0 | while read -r -d $'%pre%' D; do
    find "$D" -maxdepth 2 -mindepth 1
done
' D; do find "$D" -maxdepth 2 -mindepth 1 done

O motivo para fazer isso dessa maneira é que você pode achar confuso / complicado com vários -exec , enquanto ainda evita problemas com nomes de arquivo peculiares \ n "", etc. -print0 usará separadores nulos entre os resultados .

    
por 27.02.2017 / 22:45
0

Com base no que você começou:

find -type d -path *wp-content/plugins/* | egrep -o "wp-content/plugins/[^/]+($|/)" | sed -r "s~wp-content/plugins/([^/]+)($|/)~~" | uniq  

egrep pega * wp-content / plugins / * e qualquer caractere até a próxima barra / ou fim de linha $ - que inclui a parte que você deseja.

sed , com um delimitador ~, seleciona a parte que você deseja usando o primeiro conjunto de parênteses () e usa \ 1 (o que você quer) como a substituição de tudo

uniq filtra os resultados duplicados

    
por 27.02.2017 / 23:50