Necesito cambiar el nombre de aprox. 70,000 archivos. Por ejemplo: de sb_606_HBO_DPM_0089000a sb_606_dpm_0089000etc.
El rango de números va de 0089000a 0163022. Es solo la primera parte del nombre que necesita cambiar. Todos los archivos están en un solo directorio y están numerados secuencialmente (una secuencia de imágenes). Los números deben permanecer sin cambios.
Cuando intento esto en bash, me sorprende que la "Lista de argumentos sea demasiado larga".
Editar:
Primero intenté renombrar un solo archivo con mv:
mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx
Luego intenté renombrar un rango (aprendí aquí la semana pasada cómo mover una carga de archivos, así que pensé que la misma sintaxis podría funcionar para renombrar los archivos ...). Yo creo que probé el siguiente (o algo parecido):
mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx

ARG_MAXlímite del shell . Como esta pregunta solicita explícitamente una solución de línea de comandos, las soluciones GUI (posiblemente iguales) como en la otra pregunta tampoco coinciden.mv {1..2} {3..4}no funciona, lo cual es un problema completamente diferente deARG_MAX... ¡Todos los que respondieron probablemente sentirán lo mismo! Por lo tanto, desde mi punto de vista, desearía que revierta su última edición y, si lo desea, haga una pregunta completamente nueva acerca demvlos rangosargument list too longerror. No hay necesidad de aclarar más, esto claramente no es una trampa ya que necesitamos una solución alternativa para tratar con ARG_MAX y las respuestas en el duplicado propuesto no lo hacen.Respuestas:
Una forma es usar
findcon-exec, y la+opción. Esto construye una lista de argumentos, pero divide la lista en tantas llamadas como sea necesario para operar en todos los archivos sin exceder la lista máxima de argumentos. Es adecuado cuando todos los argumentos serán tratados de la misma manera. Este es el caso conrename, aunque no conmv.Es posible que deba instalar Perl rename:
Entonces puedes usar, por ejemplo:
Eliminar
-ndespués de la prueba, para cambiar el nombre de los archivos.fuente
Voy a sugerir tres alternativas. Cada uno es un comando simple de una sola línea, pero proporcionaré variantes para casos más complicados, principalmente en el caso de que los archivos a procesar se mezclen con otros archivos en el mismo directorio.
mmv
Me gustaría usar el comando MMV del paquete del mismo nombre :
Tenga en cuenta que los argumentos se pasan como cadenas, por lo que la expansión global no se produce en el shell. El comando recibe exactamente dos argumentos y luego encuentra los archivos correspondientes internamente, sin límites estrictos en la cantidad de archivos. También tenga en cuenta que el comando anterior asume que todos los archivos que coincidan con el primer glob serán renombrados. Por supuesto, eres libre de ser más específico:
Si tiene archivos fuera del rango de números solicitados en el mismo directorio, podría ser mejor con el ciclo sobre los números que figuran más adelante en esta respuesta. Sin embargo, también podría usar una secuencia de invocaciones de mmv con patrones adecuados:
recorrer los números
Si desea evitar instalar cualquier cosa, o necesita seleccionar por rango de números evitando coincidencias fuera de este rango, y está preparado para esperar 74,023 invocaciones de comandos, puede usar un bucle bash simple:
Esto funciona particularmente bien aquí ya que no hay espacios en la secuencia. De lo contrario, es posible que desee verificar si el archivo fuente realmente existe.
Tenga en cuenta que, en contraste con
for ((i=89000; i<=163022; ++i))la expansión de llaves, maneja los ceros iniciales desde que se lanzó Bash hace un par de años. En realidad, solicité un cambio, así que estoy feliz de ver casos de uso.Lecturas adicionales: Expansión de llaves en las páginas de información de Bash, particularmente la parte sobre
{x..y[..incr]}.recorrer los archivos
Otra opción sería recorrer un globo adecuado, en lugar de simplemente recorrer el rango entero en cuestión. Algo como esto:
Nuevamente, esta es una
mvinvocación por archivo. Y de nuevo, el ciclo está sobre una larga lista de elementos, pero la lista completa no se pasa como argumento a un subproceso, sino que se maneja internamente por bash, por lo que el límite no le causará problemas.Lectura adicional: Expansión de parámetros de Shell en las páginas de información de Bash, documentando
${parameter/pattern/string}entre otros.Si desea restringir el rango de números al que proporcionó, puede agregar un cheque para eso:
Aquí
${i##pattern}elimina la coincidencia de prefijo más largapatternde$i. El prefijo más largo se define como cualquier cosa, luego un guión bajo, luego cero o más ceros. Este último se escribe como*(0)un patrón de globo extendido que depende de laextglobopción que se configure. Eliminar los ceros a la izquierda es importante para tratar el número como base 10 y no como base 8. El+([0-9])argumento en el bucle es otro globo extendido, que coincide con uno o más dígitos, en caso de que tenga archivos allí que comiencen igual pero no terminen en un número.fuente
Una forma de evitar el
ARG_MAXlímite es usar el basil shell de bashprintf:Ex.
pero
fuente
finden el directorio actual.para todos los archivos-type fy hacer cambiar el nombre del archivo que se encuentra$1con el reemplazoHBO_DPMdedmpuno por uno-exec ... \;reemplace
echoconmvpara realizar el cambio de nombre.fuente
Podrías escribir un pequeño script de Python, algo como:
Guarde eso como un archivo de texto como
rename.pyen la carpeta en la que están los archivos, luego con el terminal en esa carpeta vaya:fuente
Puede hacerlo archivo por archivo (puede llevar algo de tiempo) con
Al igual que el Perl
renameusado en otras respuestas,rename.ultambién tiene una opción-no--no-actpara probar.fuente
-nbandera que usé para probar y sugirió que también se puede usarrename.ul.Veo que nadie ha invitado a mi mejor amigo
seda la fiesta :). El siguienteforciclo logrará su objetivo:Hay muchas herramientas para tal trabajo, seleccione la que sea más comprensible para usted. Este es simple y fácil de modificar para adaptarse a este u otros propósitos ...
fuente
$ien la sustitución de comandos, pero no hay una manera fácil de manejar una nueva línea final en el nombre del archivo.Dado que estamos dando opciones, aquí hay un enfoque de Perl.
cden el directorio de destino y ejecute:Explicación
perl -e: ejecuta el script dado por-e.foreach(glob){}: ejecuta lo que esté en{ }cada resultado del globo.glob("sb_*"): devuelve una lista de todos los archivos y directorios en el directorio actual cuyos nombres coinciden con el shell globsb*.rename $_, s/_HBO_DPM_/_dpm_/r: perl magic.$_es una variable especial que contiene cada elemento sobre el que estamos iterando (en elforeach). Entonces, aquí, se encontrará cada archivo.s/_HBO_DPM_/_dpm_/reemplaza la primera aparición de_HBO_DPM_con_dpm_. Se ejecuta$_de manera predeterminada, por lo que se ejecutará en cada nombre de archivo. El/rmedio "aplica este reemplazo a una copia de la cadena de destino (el nombre del archivo) y devuelve la cadena modificada.renameHace lo que esperaría: cambia el nombre de los archivos. Así que todo cambiará el nombre del archivo actual ($_) a sí mismo con_HBO_DPM_reemplazado por_dpm_.Podría escribir lo mismo que un script expandido (y más legible):
fuente
Dependiendo del tipo de cambio de nombre que esté imaginando, usar vidir con edición de líneas múltiples puede ser satisfactorio.
En su caso particular, puede seleccionar todas las líneas en su editor de texto y eliminar la parte _ " HBO" de los nombres de archivo con pocas teclas.
fuente
vidir?