Sim, estou classificando minha música. Eu tenho tudo organizado lindamente no seguinte mantra: /Artist/Album/Track - Artist - Title.ext
e, se houver, a capa fica /Artist/Album/cover.(jpg|png)
.
Quero examinar todos os diretórios de segundo nível e encontrar os que não têm capa. No segundo nível, quero dizer que não me importo se /Britney Spears/
não tiver um cover.jpg, mas me importaria se /Britney Spears/In The Zone/
não tivesse um.
Não se preocupe com o download da capa (esse é um projeto divertido para mim amanhã). Só me preocupo com o glorioso entusiasmo por um find
exemplo inverso .
Respostas:
Caso 1: você sabe o nome exato do arquivo a procurar
Use
find
comtest -e your_file
para verificar se existe um arquivo. Por exemplo, você procura por diretórios que não contêmcover.jpg
neles:É sensível a maiúsculas.
Caso 2: você quer ser mais flexível
Você não tem certeza do caso, e a extensão pode ser
jPg
,png
...Explicação:
sh
para cada diretório, pois a tubulação não é possível ao usarfind
ls -1 "{}"
gera apenas os nomes dos arquivos do diretório quefind
está atravessandoegrep
(em vez degrep
) usa expressões regulares estendidas;-i
faz com que o caso de pesquisa seja insensível,-q
omite qualquer saída"^cover\.(jpg|png)$"
é o padrão de pesquisa. Neste exemplo, ele correspondecOver.png
, por exemplo ,Cover.JPG
oucover.png
. O.
deve ser escapado, caso contrário, significa que ele corresponde a qualquer caractere.^
marca o início da linha,$
seu fimOutros exemplos de padrões de pesquisa para egrep :
Substitua a
egrep -i -q "^cover\.(jpg|png)$"
peça por:egrep -i -q "cover\.(jpg|png)$"
: Também correspondecd_cover.png
,album_cover.JPG
...egrep -q "^cover\.(jpg|png)$"
: Correspondecover.png
,cover.jpg
mas NÃOCover.jpg
(a distinção entre maiúsculas e minúsculas não está desativada)egrep -iq "^(cover|front)\.jpg$"
: correspondefront.jpg
, por exemplo ,Cover.JPG
mas nãoCover.PNG
Para mais informações, consulte Expressões regulares .
fonte
test
.-exec bash -c '[[ -n $(find "{}" -iname "cover.*") ]]' \;
mas isso é bastante imundo em termos de otimização. Mas funciona.test
uma carga de-o EXPRESSION
consultas OR ... por exemplo: otest -e "{}/cover.jpg" -o -e "{}/cover.png"
que é melhor do que fazer uma pesquisa completa, mas ainda diferencia maiúsculas de minúsculas.$
o nome do diretório (Ke $ ha, por exemplo).Simples, transparece. A seguir, obtém uma lista de diretórios com a capa e a compara com uma lista de todos os diretórios de segundo nível. As linhas que aparecem nos dois "arquivos" são suprimidas, deixando uma lista de diretórios que precisam de cobertura.
Viva.
Notas:
comm
Os argumentos de são os seguintes:-1
suprimir linhas exclusivas para file1-2
suprimir linhas exclusivas para file2-3
suprimir linhas que aparecem nos dois arquivoscomm
leva apenas arquivos, daí o<(...)
método de entrada excêntrico . Isso canaliza o conteúdo através de um arquivo [temporário] real.comm
precisa de entrada classificada ou não funciona efind
de forma alguma garante um pedido. Ele também precisa ser único. A primeirafind
operação pode encontrar vários arquivos paracover.*
que possa haver entradas duplicadas.sort -u
rapidamente agrupa esses números em um. A segunda descoberta sempre será única.dirname
é uma ferramenta útil para obter o diretório de um arquivo sem recorrer ased
(et al).find
ecomm
são ambos um pouco bagunçados com sua saída. A finalsed
está lá para limpar as coisas, para que você fique com eleArtist/Album
. Isso pode ou não ser desejável para você.fonte
find
pode ser simplificadofind ~/Music/ -iname 'cover.*' -printf '%h\n'
, evitando a necessidadedirname
. emboradirname
seja útil em outro lugar.É muito melhor resolver com globbing do que com find.
Agora, suponha que você não tenha arquivos perdidos nessa bela estrutura. O diretório atual contém apenas subdiretórios de artistas e esses contêm apenas subdiretórios de álbuns. Então podemos fazer algo assim:
A
<(...)
sintaxe é a substituição do processo Bash: permite usar um comando no lugar de um argumento de arquivo. Permite tratar a saída de um comando como um arquivo. Portanto, podemos executar dois programas e obter as diferenças deles, sem salvar sua saída em arquivos temporários. Odiff
programa pensa que está trabalhando com dois arquivos, mas na verdade está lendo de dois canais.O comando que produz a entrada de mão direita para
diff
,printf "%s\n" */*
, apenas lista os diretórios do álbum. O comando à esquerda percorre os*.cover
caminhos e imprime seus nomes de diretório.Execução de teste:
Aha, os diretórios
a/b
efoo/bar
não têmcover.jpg
.Existem alguns casos de esquina quebrados, como se por padrão se
*
expandisse para si mesmo se não corresponder a nada. Isso pode ser resolvido com o Bash'sset -o nullglob
.fonte
comm
seriam mais limpas do quediff
?comm -3 <(printf "%s\n" */*/cover* | sed -r 's/\/[^\/]+$//' | sort -u) <(printf "%s\n" */*)
parece um compromisso sensato, sem nenhumdiff
cotão. É, no entanto, um pouco mais lento que o meu duplo achado.Irá mostrar todos os diretórios que não possuem arquivos txt.
fonte