Sí, estoy ordenando mi música. Tengo todo arreglado maravillosamente en el siguiente mantra: /Artist/Album/Track - Artist - Title.exty si existe uno, la cubierta se asienta /Artist/Album/cover.(jpg|png).
Quiero escanear todos los directorios de segundo nivel y encontrar los que no tienen una tapa. Por segundo nivel, quiero decir que no me importa si /Britney Spears/no tiene una cover.jpg, pero me importaría si /Britney Spears/In The Zone/no tuviera una.
No se preocupe por la descarga de la portada (ese es un proyecto divertido para mí mañana). Solo me importa la gloriosa bash-fuiness sobre un findejemplo inverso .

Respuestas:
Caso 1: conoce el nombre exacto del archivo que debe buscar
Use
findcontest -e your_filepara verificar si existe un archivo. Por ejemplo, busca directorios que no tienencover.jpgen ellos:Sin embargo, es sensible a mayúsculas y minúsculas.
Caso 2: quieres ser más flexible
No está seguro del caso, y la extensión podría ser
jPg,png...Explicación:
shpara cada directorio, ya que no se pueden establecer tuberías al usarfindls -1 "{}"genera solo los nombres de archivo del directorio quefindestá atravesando actualmenteegrep(en lugar degrep) usa expresiones regulares extendidas;-ihace que el caso de búsqueda sea insensible,-qhace que omita cualquier salida"^cover\.(jpg|png)$"Es el patrón de búsqueda. En este ejemplo, coincidecOver.png, por ejemplo ,Cover.JPGocover.png. El.debe escapar, de lo contrario significa que coincide con cualquier personaje.^marca el inicio de la línea,$su finalOtros ejemplos de patrones de búsqueda para egrep :
Sustituya la
egrep -i -q "^cover\.(jpg|png)$"parte con:egrep -i -q "cover\.(jpg|png)$": También coincidecd_cover.png,album_cover.JPG...egrep -q "^cover\.(jpg|png)$": Coincidecover.png,cover.jpgpero NOCover.jpg(la distinción entre mayúsculas y minúsculas no está desactivada)egrep -iq "^(cover|front)\.jpg$": coincidefront.jpg, por ejemplo ,Cover.JPGpero noCover.PNGPara obtener más información sobre esto, consulte Expresiones regulares .
fuente
test.-exec bash -c '[[ -n $(find "{}" -iname "cover.*") ]]' \;pero eso es bastante sucio en términos de optimización. Sin embargo, funciona.testuna gran cantidad de-o EXPRESSIONconsultas OR ... por ejemplo: lotest -e "{}/cover.jpg" -o -e "{}/cover.png"que es mejor que hacer una búsqueda completa, pero aún distingue entre mayúsculas y minúsculas.$en el nombre del directorio (Ke $ ha, por ejemplo).Simple, transpira. A continuación se obtiene una lista de directorios con la portada y se compara con una lista de todos los directorios de segundo nivel. Las líneas que aparecen en ambos "archivos" se suprimen, dejando una lista de directorios que necesitan cubiertas.
¡Hurra!
Notas:
commLos argumentos son los siguientes:-1suprimir líneas exclusivas del archivo1-2suprimir líneas exclusivas de file2-3suprimir líneas que aparecen en ambos archivoscommsolo toma archivos, de ahí el<(...)método de entrada kooky . Esto canaliza el contenido a través de un archivo real [temporal].commnecesita una entrada ordenada o no funciona yfindde ninguna manera garantiza un pedido. También debe ser único. La primerafindoperación podría encontrar varios archivos, porcover.*lo que podría haber entradas duplicadas.sort -urápidamente despeina a esos a uno. El segundo hallazgo siempre será único.dirnamees una herramienta útil para obtener el directorio de un archivo sin recurrir ased(et al).findycommambos son un poco desordenados con su salida. La finalsedestá ahí para limpiar las cosas para que te quedesArtist/Album. Esto puede o no ser deseable para usted.fuente
findposiblemente se pueda simplificarfind ~/Music/ -iname 'cover.*' -printf '%h\n', evitando la necesidad de hacerlodirname. aunquedirnamees útil en otros lugares.Esto es mucho mejor para resolver con globbing que con find.
Ahora suponga que no tiene archivos perdidos en esta bonita estructura. El directorio actual contiene solo subdirectorios de artistas, y esos contienen solo subdirectorios de álbumes. Entonces podemos hacer algo como esto:
La
<(...)sintaxis es la sustitución del proceso Bash: le permite usar un comando en lugar de un argumento de archivo. Le permite tratar la salida de un comando como un archivo. Entonces podemos ejecutar dos programas y tomar su diff, sin guardar su salida en archivos temporales. Eldiffprograma cree que está trabajando con dos archivos, pero en realidad está leyendo desde dos canales.El comando que produce la entrada a mano derecha
diff,printf "%s\n" */*, solo muestra los directorios del álbum. El comando de la mano izquierda recorre las*.coverrutas e imprime sus nombres de directorio.Prueba de funcionamiento:
Ajá, los directorios
a/byfoo/barno tienencover.jpg.Hay algunos casos de esquina rota, por ejemplo, de forma predeterminada se
*expande a sí mismo si no coincide con nada. Esto se puede solucionar con Bash'sset -o nullglob.fuente
commsería más limpio quediff?comm -3 <(printf "%s\n" */*/cover* | sed -r 's/\/[^\/]+$//' | sort -u) <(printf "%s\n" */*)parece un compromiso razonable sin ninguna dedifflas pelusas. Sin embargo, es un poco más lento que mi doble hallazgo.Mostrará todos los directorios que no tengan archivos txt en ellos.
fuente