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?
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?
Respostas:
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).
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).
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
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.
.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.)