Tengo varios miles de archivos en un directorio que me gustaría clasificar en directorios como este:
De esto:
└── Files
├── AAA.mkv
├── AAA.nfo
├── AAA-picture.jpg
├── BBB.mp4
├── BBB.srt
├── BBB-clip.mp4
├── CCC.avi
├── CCC.srt
├── CCC-clip.mov
└── CCC.nfo
A esto:
└── Files
├── AAA
│ ├── AAA.mkv
│ ├── AAA.nfo
│ └── AAA-picture.jpg
├── BBB
│ ├── BBB.mp4
│ ├── BBB.srt
│ └── BBB-clip.mp4
└── CCC
├── CCC.avi
├── CCC.srt
├── CCC-clip.mov
└── CCC.nfo
Los nombres de los archivos varían en longitud y número de palabras, a veces separados por espacios y posiblemente algunos con guiones (además de los que terminan en '-short'. Son principalmente archivos de video con una variedad de formatos / contenedores: mov / mpg / mkv / mp4 / avi / ogg. Algunos están subtitulados. Algunos tienen archivos con metadatos asociados (.nfo o -clip)
Editar: Los archivos principales son videos (aquí es donde me gustaría dibujar el nombre del directorio). Los archivos asociados representan metadatos. Algunos diferentes en nombres solo por la extensión. Hay una media docena de otras variaciones en el nombre de archivo base como -clip.mp4 -clip.mov o -picture.jpg Pensé que si se sugería algo con esos pocos, entonces podría (con suerte) resolver el resto. En resumen, AAA.mkv se mueve a un directorio llamado AAA. Luego, todos los archivos de metadatos que comienzan con AAA se unen (es decir, en este ejemplo: AAA-picture.jpg y AAA.nfo). Entonces, el nombre base es de hecho una subcadena en el caso del archivo AAA-picture.jpg. Diría que probablemente es relativamente seguro usar simplemente el guión como factor de delimitación ... aunque '-clip' o '-picture' en su totalidad sería más seguro.
¿Cómo puedo hacer esto sin tener el síndrome del túnel carpiano? Miré esto, pero era lo suficientemente diferente como para que mis débiles habilidades de secuencias de comandos fracasaran.
Gracias.
AAA-picture.jpg
? ¿Qué se supone que es la "regla" que determina cómo crear una carpeta? ¿Qué cantidad del nombre de archivo se debe extraer? Por supuesto, podemos dividir nombres de archivos usando.
y-
como separadores y extraer la primera parte. Pero también dices que pueden separarse por espacios y otros caracteres, entonces pregunta si siguen la misma regla,AAA
luego separador y luego otro texto.AAA
yAAA-picture
. En este caso, sin embargo, quiere ambosAAA.mkv
yAAA-picture.jpg
estar debajo de laAAA
carpeta. Esto no es una extracción de nombre base, es una extracción de subcadena, o al menos dividir el nombre de archivo en múltiples separadores y usar la primera cadena como nombre de directorio.BBB-clip.mp4
yCCC-clip.mov
Respuestas:
Si bien su pregunta está etiquetada
bash
, sería un tanto problemático (en mi humilde opinión) usarlobash
para dicha tarea. Sugeriría usar Python porque tiene muchas buenas funciones para tareas complejas y esta respuesta proporciona una solución usando ese lenguaje.Esencialmente, lo que ocurre aquí es que usamos expresiones regulares para dividir nombres de archivos en múltiples delimitadores, obtener solo la primera parte y usar un conjunto único de esas primeras partes como nombres básicos para nuevos directorios.
Luego recorremos el directorio superior nuevamente y clasificamos los archivos en sus lugares apropiados.
El script no hace nada espectacular, y en realidad en el análisis de algoritmos esto no funcionaría demasiado bien, debido a los bucles anidados, pero para una solución "rápida y sucia, pero viable" está bien. Si está interesado en lo que hace cada línea, hay muchos comentarios agregados para explicar la funcionalidad
Tenga en cuenta que la demostración solo muestra la impresión de los nuevos nombres de archivo solo con fines de prueba. Descomente la
os.rename()
parte para mover realmente el archivo.La demo
Script en sí
Notas adicionales:
re.split()
función): agregue corchetes internos (es decir"[.-]"
) agregue los caracteres que desee.os.rename()
función. Alternativamente, podríaimport shutil
y usar lashutil.move()
función. Ver https://stackoverflow.com/a/8858026/3701431fuente
Hice un pequeño script bash para hacer esto, simplificado y mejorado gracias a los comentarios de OP, @dannysauer, @Arronical y @Scott
Ejecutar con
echo
primero y luego eliminarecho
para mover realmente los archivos. La secuencia de comandos debe ejecutarse desde el directorio donde desea mover los archivos. Si lo prefiere, aquí está como un comando de una línea:(de nuevo, eliminar
echo
después de la prueba)Explicación:
for file in *; do mkdir -p "${file%%[.-]*}"
haga un directorio con el nombre de la primera parte del nombre de cada archivo (hasta el primer guión o punto) La-p
bandera es muy importante aquí; sin ella, el script moverá solo el primer archivo coincidente (gracias a Arronical por señalar eso-p
evitará quemkdir
intentes crear directorios existentes y te quejes de ello )2>/dev/null
el script se queja de que no puede crear un directorio con el mismo nombre que él mismo (pero aún funciona), por lo que descartamos el error; esto no es necesario cuando se ejecuta como una líneaif [[ -d "${file%%[.-]*}" ]]; then
si hay un directorio con ese nombre (simkdir
fue exitoso) entonces ...if [[ -f "$file" ]]
si estamos tratando con un archivo (no un directorio u otra cosa) entonces ...mv -v -- "$file" "${file%%[.-]*}"
moverlo al directorio correspondiente.fuente
~/.bashrc
función;)mkdir -p
que no se queja de directorios ya existentes..
. (2) La línea 7 de la secuencia de comandos se refiere afilenames
, que, en ese punto, es igual al último nombre de archivo (lexicográficamente) en el directorio. ¿A qué te refieresfiles
? (3) En la línea 6, ¿por qué no solo decirfor files in "$dirs".* "$dirs"-*
? (4) Como cuestión de estilo, prefiero decirfor dir in …
yfor file in …
; es decir, use palabras singulares para la variable de índice de bucle (que toma solo un valor a la vez).find
. Te debo un trago :)En un pequeño script de Python:
Para usarlo:
move_into.py
Ejecútelo con el directorio como argumento:
El script asume que todos los archivos (relevantes) tienen extensiones. Si un archivo no tiene extensión, no pasa nada con él. Si eso es un problema, por favor mencione que se puede cambiar fácilmente.
Explicación
Posteriormente, el archivo se mueve a la carpeta correspondiente.
fuente