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:
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 -Eexpressão regular estendida (como em grep -E).
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).
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:
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 "???*".
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.
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.)
Respostas:
Supondo que você esteja usando o GNU
find
(que provavelmente é, uma vez que-iregex
é uma extensão do GNU para POSIXfind
)-regex
e o-iregex
padrão para expressões regulares do Emacs, que não reconhecem{3,}
. Você precisa especificar um tipo diferente de expressões regulares usando a-regextype
opção; Além disso, você precisa ajustar sua expressão regular ao fato de a expressão corresponder ao caminho completo:Você também deve escapar do
.
para que ele corresponda a "." em vez de qualquer caractere:A expressão regular pode ser simplificada, uma vez que nos preocupamos apenas com três caracteres não - "/":
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:ou:
Sem
-E
, isso é expressão regular básica (como emgrep
) e com-E
expressão regular estendida (como emgrep -E
).Com ast-open's
find
:(isso é regexps estendidos fora da caixa).
fonte
Aqui é mais fácil com curingas padrão:
Ou com algumas
find
implementações (aquelas que suportam-regex
também suportam-iname
):Para números arbitrários de caracteres em vez de
3
, é aí que você pode preferir reverter para-iregex
onde estiver disponível (consulte a resposta de @Stephen Kitt ) ou usarzsh
ouksh93
globs:zsh
:(a
(D)
considerar arquivos ocultos e arquivos em diretórios ocultos como comfind
)(#cx,y)
é ozsh
equivalente 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
:@(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)
éksh93
equivalente a regexpz{x,y}
.~(i:...)
: correspondência que não diferencia maiúsculas de minúsculas.Os globos têm algumas vantagens extras por
find
aqui: você obtém uma lista classificada (você pode desativar essa classificaçãozsh
com ooN
qualificador 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, afind
abordagem falharia em relatar a,$'St\xE9phane Chazelas - CV.pdf
pois o\xE9
fato de não ser um caractere não corresponde ao regexp.
ou curinga?
ou*
ao GNUfind
).fonte
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
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
.pdf
nos nomes deles . Só porque um arquivo tem os caracteres.pdf
no 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:
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 ...
Então, usando
-iname
isso, 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
file
comando Uma opção gera o tipo MIME , que é mais simples de analisar. Afind
consulta então se torna simples-name "???*"
.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}
.Agora vamos terminar inventando para incluir arquivos PDF nomeados
a
eabc
: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
updatedb
para criar um índice de arquivo pesquisável, emlocate
vez defind
ler esse índice e emparallel
vez dexargs
encadear. 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.fonte
.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.)