Como marcar diretórios na saída do comando `find`?

Como marcar diretórios na saída do comando `find`?

Por exemplo, estou procurando arquivos e diretórios em algum diretório:

ubuntu@example:/etc/letsencrypt$ sudo find . -name example.com*
./archive/example.com
./renewal/example.com.conf
./live/example.com
ubuntu@example:/etc/letsencrypt$ 

Como posso marcar isso ./archive/example.come ./live/example.comos diretórios estão na saída acima?

Responder1

Imprima o tipo de arquivo junto com o nome com -printf "%y %p\n":

$ sudo find . -name 'example.com*' -printf "%y %p\n"
d ./archive/example.com
f ./renewal/example.com.conf
d ./live/example.com

O uso de -printfassume GNU find(a implementação mais comum findem sistemas Linux).

Responder2

Encontre duas vezes:

echo 'directories'
find . -name 'example.com*'   -type d

echo 'non-directories'
find . -name 'example.com*' ! -type d

Observe também a citação do padrão usado para o teste de nome. Sem aspas, o shell tentaria comparar a string com os nomes no diretório atual antes de chamar find. Se a failglobopção shell fosse definida no bashshell, ou se a NOMATCHopção shell zshnão fosse desativada, um padrão globbing sem aspas que não correspondesse a nada geraria um erro no shell e findnão seria chamado.


Como alternativa, basta exibir uma barra no final dos nomes dos caminhos dos diretórios (é assim que ls -prepresentaria os diretórios):

find . -name 'example.com*' \( -type d -exec printf '%s/\n' {} \; -o -print \)

O comando acima findtesta primeiro se o nome está correto. Se for, e for um diretório, ele chama printfpara gerar o nome do caminho do diretório com uma barra no final. Se não for, um diretório -printserá usado apenas para gerar o nome do caminho como está.

Com o GNU find, o -exec printf '%s/\n' {} \;bit poderia ser substituído por -printf '%p/\n'.

Com standard find, você também pode -exec printf '%s/\n' {} +chamar o printfutilitário externo o menor número de vezes possível, mas isso significaria que os diretórios provavelmente seriam gerados por último, ou pelo menos em lotes.


Outra alternativa é realmente usar ls -ppara diferenciar os diretórios de outros tipos de arquivo. Usando ls -p, um diretório seria listado com um /caractere final, assim como acima.

find . -name 'example.com*' -exec ls -f -d -p {} +

Estou usando -faqui para evitar lsclassificar a saída e -devitar listar oconteúdode diretórios.

Você poderia usar ls -Fem vez de ls -ptambém colocaroutromarcas em tipos de arquivos diferentes de diretórios. Por exemplo, os executáveis ​​teriam o sufixo de *e os links simbólicos teriam o sufixo de @.

Ambos -pe -F(e -fe -d) são opções padrão para o lsutilitário.

Responder3

Você pode usar fileassim:

sudo find . -name "example.com*" -print0 | xargs  -0 sudo file

Exemplo de saída:

$ sudo find .  -name "example.com*"   -print0 | xargs  -0 sudo file
./example.com. big file: ASCII text
./example.com-dir:       directory
./example.com:           empty

Responder4

Se você deseja uma opção mais portátil que funcione com sabores *nix sem a -printfopção gnu (macOS, por exemplo), você pode adicionar uma barra no final dos caminhos de diretório da lsseguinte forma:

find . -name "example.com*" -exec ls -dF {} \;

exemplo:

$ sudo find . -name "example.com*" -exec ls -dF {} \;
./archive/example.com/
./renewal/example.com.conf
./live/example.com/

Isso também está em um formato mais adequado para canalização adicional para mais comandos unix.

informação relacionada