varios texto renombrar para nombre masivo directorio convertir comando cambiar archivos archivo linux bash file-extension

texto - renombrar directorio linux



Convierta todas las extensiones de archivo a minĂºsculas (10)

Bueno, podrías usar este fragmento como el núcleo de cualquier alternativa que necesites:

#!/bin/bash # lowerext.sh while read f; do if [[ "$f" = *.* ]]; then # Extract the basename b="${f%.*}" # Extract the extension x="${f##*.}" # Convert the extension to lower case # Note: this only works in recent versions of Bash l="${x,,}" if [[ "$x" != "$l" ]]; then mv "$f" "$b.$l" fi else continue fi done

Después, todo lo que necesita hacer es alimentar una lista de los archivos que necesita cambiar el nombre a su entrada estándar. Por ejemplo, para todos los archivos bajo el directorio actual y cualquier subdirectorio:

find -type f | lowerext.sh

Una pequeña optimización:

find -type f -name ''*.*'' | lowerext.sh

Tendrás que ser más específico si necesitas una respuesta más concreta que esta ...

Estoy tratando de minúsculas todas mis extensiones, independientemente de lo que sea. Hasta ahora, por lo que he visto, debe especificar qué extensiones de archivo desea convertir a minúsculas. Sin embargo, solo quiero minúsculas de todo después del primer último punto . en el nombre.

¿Cómo puedo hacer eso en bash ?


Entonces, estas soluciones que se parecen al ruido de línea son agradables y todo, pero esto es fácil de hacer con el REPL de python (sé que el OP pidió bash, pero Python está instalado en muchos sistemas que tienen bash estos días ... )

rename ''s//.JPG$//.jpg/'' *


Esto es más corto pero más general, combinado con la respuesta de los demás:

rename ''s//.([^.]+)$/./L$1/'' *

Simulación

Para la simulación, use -n , es decir, rename -n ''s//.([^.]+)$/./L$1/'' * . De esta manera, puede ver qué se cambiará antes de que se realicen los cambios reales. Ejemplo de salida:

Happy.Family.GATHERING.JPG renamed as Happy.Family.GATHERING.jpg Hero_from_The_Land_Across_the_River.JPG renamed as Hero_from_The_Land_Across_the_River.jpg rAnD0m.jPg1 renamed as rAnD0m.jpg1

Breve explicación sobre la sintaxis

  • La sintaxis es rename OPTIONS ''s/WHAT_TO_FIND_IN_THE_NAME/THE_REPLACEMENT/'' FILENAMES
  • /.([^.]+)$ significa secuencia de cualquier cosa menos punto ( [^.] ) al final de la cadena ( $ ), después del punto ( /. )
  • ./L$1 significa punto ( /. ) Seguido de minúsculas ( /L ) del primer grupo ( $1 )
  • El primer grupo en este caso es la extensión ( [^.]+ )
  • Es mejor utilizar comillas simples '' lugar de comillas dobles " para ajustar la expresión regular para evitar la expansión de shell

Esto hará el trabajo para su ''.mp3, pero solo en el directorio de trabajo, sin embargo, puede consumir nombres de archivo con espacios en blanco:

for f in *.[mM][pP]3; do mv "$f" "${f%.*}.mp3"; done

Corrección:

for f in *.[mM][pP]3; do [[ "$f" =~ /.mp3$ ]] || mv "$f" "${f%.*}.mp3"; done


Si estás usando ZSH:

zmv ''(*).(*)'' ''$1.$2:l''

Si obtiene zsh: command not found: zmv , simplemente ejecute:

autoload -U zmv

Y luego intenta de nuevo.

Gracias a este artículo original por el consejo sobre zmv y la documentación de ZSH para la sintaxis de sustitución en minúscula / mayúscula.


Si solo le interesan determinadas extensiones de archivo, como convertir todas las extensiones "JPG" en mayúsculas a minúsculas "jpg", puede utilizar la utilidad de línea de comandos para cambiar el nombre . CD en el directorio que desea cambiar. Entonces

import os files = os.listdir(''.'') for f in files: path, ext = os.path.splitext(f) if ext.isupper(): os.rename(f, path + ext.lower())

Usa la opción -n para probar qué cambiará, y luego cuando estés contento con los resultados, usa sin

rename -n ''s//.JPG$//.jpg/'' *


Si tiene mmv (= mover varios archivos) instalado y sus nombres de archivo contienen como máximo un punto, puede usar

mmv -v "*.*" "#1.#l2"

No obtiene más de un punto a la derecha (dado que el algoritmo de coincidencia para * no es codicioso en mmv ), sin embargo, maneja () y '' correctamente '' . Ejemplo:

$ mmv -v "*.*" "#1.#l2" FOO.BAR.MP3 -> FOO.bar.mp3 : done foo bar ''baz'' (CD 1).MP3 -> foo bar ''baz'' (CD 1).mp3 : done

No es perfecto, pero es mucho más fácil de usar y recordar que todas las cosas de find/exec/sed .


Tuve éxito con este comando.

rename JPG jpg *.JPG

Donde rename es un comando que le dice al shell que cambie el nombre de cada aparición de JPG a jpg en la carpeta actual con todos los nombres de archivo con la extensión JPG .

Si ve Bareword "JPG" no permitido mientras que "strict subs" en uso en (eval 1) línea 1 con este enfoque intente:

rename ''s//.JPG$/.jpg/'' *.JPG


recursivamente para toda una solución fina:

find -name ''*.JPG'' | sed ''s//(.*/)/.JPG/mv "/1.JPG" "/1.jpg"/'' |sh

Lo anterior recursivamente cambia el nombre de los archivos con la extensión "JPG" a los archivos con la extensión "jpg"


Solución

Puedes resolver la tarea en una línea:

find . -name ''*.*'' -exec sh -c '' a=$(echo "$0" | sed -r "s/([^.]*)/$//L/1/"); [ "$a" != "$0" ] && mv "$0" "$a" '' {} /;

Nota: esto se dividirá para los nombres de archivo que contengan líneas nuevas. Pero ten paciencia conmigo por ahora.

Ejemplo de uso

$ mkdir C; touch 1.TXT a.TXT B.TXT C/D.TXT $ find . . ./C ./C/D.TXT ./1.TXT ./a.TXT ./B.TXT $ find . -name ''*.*'' -exec sh -c ''a=$(echo "$0" | sed -r "s/([^.]*)/$//L/1/"); [ "$a" != "$0" ] && mv "$0" "$a" '' {} /; $ find . . ./C ./C/D.txt ./a.txt ./B.txt ./1.txt

Explicación

Encuentra todos los archivos en el directorio actual ( . ) Que tienen punto . en su nombre ( -name ''*.*'' ) y ejecuta el comando para cada archivo:

a=$(echo "$0" | sed -r "s/([^.]*)/$//L/1/"); [ "$a" != "$0" ] && mv "{}" "$a"

Ese comando significa: intente convertir la extensión de archivo a minúsculas (eso hace que sed ):

$ echo 1.txt | sed -r "s/([^.]*)/$//L/1/" 1.txt $ echo 2.TXT | sed -r "s/([^.]*)/$//L/1/" 2.txt

y guarda el resultado en a variable.

Si algo ha cambiado [ "$a" != "$0" ] , cambie el nombre del archivo mv "$0" "$a" .

El nombre del archivo que se está procesando ( {} ) pasó a sh -c como su argumento adicional y se ve dentro de la línea de comando como $0 . Hace que el script sea seguro, porque en este caso el shell toma {} como un dato, no como una parte del código, como cuando se especifica directamente en la línea de comando. ( Agradezco a @gniourf_gniourf por señalarme este tema realmente importante ).

Como puede ver, si usa {} directamente en el script, es posible tener algunas inyecciones de shell en los nombres de archivo, algo como:

; rm -rf * ;

En este caso, el shell considerará la inyección como parte del código y se ejecutarán.

Mientras-versión

Versión más clara, pero un poco más larga, del guión:

find . -name ''*.*'' | while IFS= read -r f do a=$(echo "$f" | sed -r "s/([^.]*)/$//L/1/"); [ "$a" != "$f" ] && mv "$f" "$a" done

Esto todavía se rompe para los nombres de archivo que contienen nuevas líneas. Para solucionar este problema, debe tener un find que admita -print0 (como GNU find ) y Bash (de modo que read soporte el -d delimitador -d ):

find . -name ''*.*'' -print0 | while IFS= read -r -d '''' f do a=$(echo "$f" | sed -r "s/([^.]*)/$//L/1/"); [ "$a" != "$f" ] && mv "$f" "$a" done

Esto aún se rompe para los archivos que contienen nuevas líneas al final (ya que serán absorbidas por la subshell a a=$(...) . Si realmente quieres un método infalible (¡y deberías hacerlo!), Con una versión reciente de Bash (Bash≥ 4.0) que admite la expansión de parámetros ,, aquí está la solución definitiva:

find . -name ''*.*'' -print0 | while IFS= read -r -d '''' f do base=${f%.*} ext=${f##*.} a=$base.${ext,,} [ "$a" != "$f" ] && mv -- "$f" "$a" done

Volver a la solución original

O en un solo find vaya (a la solución original con algunas correcciones que lo hacen realmente infalible):

find . -name ''*.*'' -type f -exec bash -c ''base=${0%.*} ext=${0##*.} a=$base.${ext,,}; [ "$a" != "$0" ] && mv -- "$0" "$a"'' {} /;

-type f para que solo se -type f los archivos normales. Sin esto, aún podría tener problemas si los nombres de los directorios se renombran antes de los nombres de los archivos. Si también desea cambiar el nombre de los directorios (y enlaces, tuberías, etc.) debe usar -depth :

find . -depth -name ''*.*'' -type f -exec bash -c ''base=${0%.*} ext=${0##*.} a=$base.${ext,,}; [ "$a" != "$0" ] && mv -- "$0" "$a"'' {} /;

para que find realice una búsqueda en profundidad.

Puede argumentar que no es eficiente generar un proceso bash para cada archivo encontrado. Eso es correcto, y la versión del ciclo anterior sería mejor.