Obtenha uma lista de nomes de diretório com find

35

Eu sei que posso fazer isso para obter uma lista de nomes de diretório:

find . -type d -maxdepth 1 

A saída é assim:

.
./foo
./bar

Eu prefiro a lista sem ./. Existe uma maneira de encontrar encontrar apenas os nomes brutos?

Tentei enviar a lista para stat para formatá-la, mas isso me dá o mesmo resultado:

find . -type d -maxdepth 1 -print0 | xargs -0 stat -f '%N'
joachim
fonte
então você quer foo bar ...tudo em uma linha sem o ./na frente?
Levon
Isso é puramente por razões estéticas / cosméticas ou você está tentando fazer algo com a saída?
Jw013

Respostas:

42

Com o GNU, findvocê pode usar a -printfopção:

find . -maxdepth 1 -type d -printf '%f\n'

Conforme observado por Paweł nos comentários, se você não deseja que o diretório atual seja listado -mindepth 1, adicione , por exemplo:

find . -mindepth 1 -maxdepth 1 -type d -printf '%f\n'
Thor
fonte
Não consigo encontrar qualquer menção à -printfopção a mais recente POSIX especificação e me pergunto como portátil é ...
rahmu
@rahmu: Isso foi testado com o GNU find. Nenhuma das printfopções é mencionada pelo POSIX e elas não parecem ser suportadas por algumas das outras findversões. A localização do GNU pode ser instalada na maioria dos lugares, portanto, nesse sentido, é portátil.
Thor
1
adicione também -mindepth 1se você quiser se livrar do.
Paweł Prażak
18

Atualizar:

Uma alternativa mais curta:

 find . -maxdepth 1 -type d | cut -c 3-

Fornecerá os nomes, um por linha, sem barras

Levon
fonte
4
@ downvoter .. um voto negativo sem explicação não ajuda ninguém (OP, SO ou eu). Esta é uma solução funcional para a pergunta do OP. Fico feliz em corrigir um erro se apontado ou melhorar a resposta, mas isso requer feedback construtivo , em vez de apenas um "clique" anônimo.
Levon
1
Fui eu que diminuiu o voto quando sua resposta incluiu a análise ls. Ao mesmo tempo, eu publiquei um link sobre por que essa é uma má idéia em outra resposta que foi excluída desde então. Na época, havia apenas 2 respostas e o motivo parecia óbvio. Estou feliz que você apontou a ambiguidade, e aqui está a minha explicação. Para que conste, entreguei meu voto negativo em um voto positivo porque concordo com a sua resposta atual.
rahmu 25/08/12
@rahmu Dar uma explicação para seu voto negativo em outra pergunta não é útil para mim (e apenas óbvio para você). Além disso, embora essa seja uma solução melhor, a solução que eu publiquei antes funcionou muito bem (sim, eu estou familiarizado com o link "não use ls" - mas não se aplica às cegas em todos os casos). Se você tiver um exemplo contrário, por que minha solução inicial não funcionaria, eu adoraria conhecê-la (para que eu possa aprender algo com isso); caso contrário, você está apenas postando um link e não oferecendo nada construtivo.
Levon
Considere que existe um \nnome em um diretório que você não pode usar cut para recuperá-lo (que é o que você estava fazendo quando eu te diminuí o voto). Existem poucos casos em lsque não se comporta perigosamente e é quase sempre mais seguro usar outra maneira.
rahmu
9

Usando o GNU find, você pode usar -mindepth para impedir que o find corresponda ao diretório atual:

find . -type d -maxdepth 1 -mindepth 1

Como você não está fazendo isso recursivamente, você pode usar um bash glob:

echo */

Adicionar um final / a uma glob fará com que apenas os diretórios sejam correspondidos.

jordanm
fonte
1
*/perde arquivos de ponto e inclui links simbólicos. Isso pode ou não ser um problema.
Gilles 'SO- stop be evil' (
@ Gilles - Sempre haverá falta de links simbólicos, mas os arquivos de ponto dependem de o ponto ou não estar configurado.
jordanm
6

Vamos sedremover esses dois caracteres:

find . -maxdepth 1 -type d | sed -e 's/^\.\///'
Birei
fonte
6

Eu prefiro usar:

 find ./ -type d -maxdepth 1 -exec basename {} \;
user1293137
fonte
2

Eu costumo usar:

find * -type d

Mas não sei se é o caminho certo para fazer o que você deseja.

Francesco Turco
fonte
1
Se você deseja deixar o shell expandir todos os nomes de arquivos, por que usar find?
Jordanm
@jordanm Para selecionar apenas diretórios. echo */faria a mesma coisa, mais ou menos (ele perde arquivos de pontos e inclui links simbólicos), mas o joachim perguntaria como remover a final /.
Gilles 'SO- stop be evil' (
0

No AIX, o parâmetro 'maxdepth' não funciona.

Em geral, isso funciona para mim:

find ./ -type d | cut -d"/" -f2 | sort -u

user1656294
fonte
0

O que você está procurando é chamado basename, ele ignora a estrutura de diretórios unix

Exemplo abaixo:

find /any/path/you/want -maxdepth 1 -type d -exec basename {} \;

ele excluirá para a saída até o caminho dir, removendo a necessidade de cd antes de executar o comando


Algumas informações adicionais:

Eu passaria -execcomo argumento para encontrar |(canal) outro comando para a saída (evitando o segundo comando passar por cada linha de saída, tendo dito que, dependendo da saída, isso poderia melhorar o desempenho do script)

NOTA: as findopções não são posicionais (-maxdepth afeta os testes especificados antes e os especificados depois).

gonzalesraul
fonte