Encontre todos os PDFs com pelo menos três caracteres no nome

9

Gostaria de encontrar os arquivos PDF cujo nome (excluindo a extensão) é maior que três.

$ find ~ -iregex ".{3,}/.pdf"

não retorna nada, mas

$ find ~ -iregex ".+/.pdf"

trabalho.

Como posso ativar a {3,}variante?

Cálculo
fonte
Que comprimento? Comprimento do nome do arquivo? Comprimento da página?
Ignacio Vazquez-Abrams

Respostas:

18

Supondo que você esteja usando o GNU find(que provavelmente é, uma vez que -iregexé uma extensão do GNU para POSIXfind ) -regexe o -iregexpadrão para expressões regulares do Emacs, que não reconhecem {3,}. Você precisa especificar um tipo diferente de expressões regulares usando a -regextypeopção; Além disso, você precisa ajustar sua expressão regular ao fato de a expressão corresponder ao caminho completo:

find ~ -regextype posix-extended -iregex '.*/[^/]{3,}.pdf'

Você também deve escapar do .para que ele corresponda a "." em vez de qualquer caractere:

find ~ -regextype posix-extended -iregex '.*/[^/]{3,}\.pdf'

A expressão regular pode ser simplificada, uma vez que nos preocupamos apenas com três caracteres não - "/":

find ~ -regextype posix-extended -iregex '.*[^/]{3}\.pdf'

Para ser completo, com o FreeBSD ou o NetBSD find(outra implementação que suporta -iregex, e não a sua, pois .+não funcionaria lá sem -E), você escreveria:

find ~ -iregex '.*[^/]\{3\}\.pdf'

ou:

find -E ~ -iregex '.*[^/]{3}\.pdf'

Sem -E, isso é expressão regular básica (como em grep) e com -E expressão regular estendida (como em grep -E).

Com ast-open's find:

find ~ -iregex '.*[^/]{3}\.pdf'

(isso é regexps estendidos fora da caixa).

Stephen Kitt
fonte
20

Aqui é mais fácil com curingas padrão:

find ~ -name '*???.[pP][dD][fF]'

Ou com algumas findimplementações (aquelas que suportam -regextambém suportam -iname):

find ~ -iname '*???.pdf'

Para números arbitrários de caracteres em vez de 3, é aí que você pode preferir reverter para -iregexonde estiver disponível (consulte a resposta de @Stephen Kitt ) ou usar zshou ksh93globs:

  • zsh:

    set -o extendedglob # best in ~/.zshrc
    printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
    

    (a (D)considerar arquivos ocultos e arquivos em diretórios ocultos como com find)

    • (#cx,y)é o zshequivalente curinga de regexp{x,y}
    • (#i) caso insensitivo
    • ?curinga padrão para qualquer caractere único (como regexp .)
    • **/: qualquer nível de subdiretórios (incluindo 0)
  • ksh93:

    FIGNORE='@(.|..)' # to consider hidden files
    set -o globstar
    printf '%s\n' **/{3,}(?).~(i:pdf)
    
    • @(x|y): operador curinga ksh estendido semelhante ao regexp (x|y).
    • FIGNORE: variável especial que controla quais arquivos são ignorados pelos globs. Quando definida, a ignorância usual de arquivos ocultos não é feita, mas ainda queremos ignorar as entradas do diretório .e ..onde estiverem presentes.
    • {x,y}(z)é ksh93equivalente a regexp z{x,y}.
    • ~(i:...): correspondência que não diferencia maiúsculas de minúsculas.

Os globos têm algumas vantagens extras por findaqui: você obtém uma lista classificada (você pode desativar essa classificação zshcom o oNqualificador glob ou usar diferentes critérios de classificação) e também funciona quando os nomes de arquivos contêm sequência de bytes que não formam caracteres válidos (por Por exemplo, em um código de idioma que usa o conjunto de caracteres UTF-8, a findabordagem falharia em relatar a, $'St\xE9phane Chazelas - CV.pdfpois o \xE9fato de não ser um caractere não corresponde ao regexp .ou curinga ?ou *ao GNU find).

Stéphane Chazelas
fonte
Isso funcionaria para o Bash? shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Wjandrea
7

Como sei que são PDFs?

Você não faz a menos que você pergunte. Claro, estou sendo pedante, mas você não perguntou sobre os arquivos .pdfnos nomes deles . Só porque um arquivo tem os caracteres .pdfno nome do arquivo não o torna um arquivo PDF .

Na verdade, vamos ser pedantes em relação a isso: se os últimos quatro caracteres do nome de um arquivo forem .pdf, ele sempre terá mais de três caracteres no nome .

Então, fazendo isso da maneira errada , você pode dizer:

$ find . -type f -name "*???.pdf"
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Setup_MagicISO.exe.pdf

Vê aquele segundo? Na verdade, é um executável. (Eu sei, mudei o nome.) E também estou perdendo um PDF que eu podia jurar estava no diretório Documentos ...

$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf

Então, usando -inameisso, poderíamos encontrar esse, mas isso ainda está transformando esse arquivo não-PDF.

O que realmente queremos fazer neste caso é examinar o número mágico do arquivo usando o filecomando Uma opção gera o tipo MIME , que é mais simples de analisar. A findconsulta então se torna simples -name "???*".

$ find . -type f -name "???*" -print0|xargs -0 file --mime
./.bash_history:                                              text/plain; charset=us-ascii
./.bash_logout:                                               text/plain; charset=us-ascii
./.bashrc:                                                    text/plain; charset=us-ascii
./.profile:                                                   text/plain; charset=us-ascii
./Documents/McLaren 720s Coupe:Order Summary.pdf:             application/pdf; charset=binary
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF: application/pdf; charset=binary
./Documents/Setup_MagicISO.exe.pdf:                           application/x-dosexec; charset=binary
./Downloads/Setup_MagicISO.exe:                               application/x-dosexec; charset=binary
./Downloads/WindowsUpdate.diagcab:                            application/vnd.ms-cab-compressed; charset=binary

Vamos usar o delimitador de dois pontos, procurar o tipo MIME application/pdf, zerar essa parte e imprimir o resultado. Tome nota, um dos meus arquivos tem dois pontos no nome; então eu não posso simplesmente pedir awk para ($2==":"){print $1}.

$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF

Agora vamos terminar inventando para incluir arquivos PDF nomeados ae abc:

$ mkdir Documents/other
$ cp -a Documents/McLaren\ 720s\ Coupe\:Order\ Summary.pdf Documents/other/a
$ cp -a Documents/Pioneer\ Premier\ DEH-P490IB\ CD\ Install\ Manual.PDF  Documents/other/abc
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
./Documents/other/abc

Isso é tudo. Eu sei que provavelmente vou ser enganado por ser terrivelmente pedante, mas no meu trabalho com milhares de volumes NFS para caçar e todos os tipos de arquivos com nomes inadequados, desejo que mais pessoas sejam pedantes.

Editado para adicionar: no mundo real, talvez eu queira usar updatedbpara criar um índice de arquivo pesquisável, em locatevez de findler esse índice e em parallelvez de xargsencadear. Isso está um pouco fora do escopo desta questão. Eu escrevi isso com a cara séria também. Por que eu me importo tanto? Eu posso estar procurando por arquivos de filme e áudio; ou certos tipos de fotografias; ou executáveis ​​binários em um diretório de dados do projeto.

Rico
fonte
1
Se o solicitante tiver a mesma situação que você, onde existem arquivos PDF cujos nomes não terminam .pdf, seu pedantismo será muito apreciado. Mas é uma situação relativamente incomum (não obstante o seu trabalho) e não temos nenhuma razão para acreditar que o solicitante realmente tenha que lidar com isso, então eu acho que o argumento que você está fazendo, apesar de válido, é meio perturbador - e acho que a maneira enérgica que você formulou leva a resposta ao reino de "(provavelmente) não é útil". (Minha opinião somente, é claro.)
David Z
Como estamos sendo pedantes, como você lidaria com PDFs como os poliglotas PoC || GTFO ?
Stephen Kitt
@StephenKitt - Não sei o que você está perguntando, mas estou intrigado. Eles me parecem PDFs comuns, com nomes não particularmente descolados. Isso falharia na minha solução sugerida?
Rich
@DavidZ Não tenho certeza do que dizer sobre isso. Quero dizer, não é um pouco pedante apontar que estou sendo pedante quando já disse isso? Eis por que "não é útil": uma boa solução para encontrar PDFs deve ser uma solução adaptável para encontrar scripts, executáveis ​​binários, bibliotecas, arquivos de mídia etc. Não consigo nem começar a ver como adaptar um dos outras respostas para "executáveis ​​mach compactados", mas estou disposto a aprender.
Rich
1
@ Muitos dos PDFs também são arquivos ZIP, alguns também são imagens ou até máquinas virtuais inicializáveis ​​... (Veja os links de “spoilers” nas primeiras edições para obter dicas; o restante está documentado nos próprios PDFs.)
Stephen Kitt