Script o programa de Linux para acortar nombres de archivos

8

No he tenido mucho éxito en encontrar una versión de Linux de namemangler , que necesito cambiar el nombre de 1000 de los archivos para que sean legibles en Windows.

¿Alguien sabe de un programa de Linux que pueda hacer esto?

De lo contrario, un script podría funcionar, ya que solo necesito cambiar el nombre de todos los archivos de una carpeta a, digamos, los primeros 16 caracteres. Sospecho que vale la pena seguir la ruta del script, pero no estoy seguro de por dónde empezar.

Grimlockz
fuente
2
Probablemente podría escribir rápidamente un script Python o Perl u Ocaml o Ruby haciendo eso.
¿Por qué no puede simplemente usar un sistema de archivos vfat, que permite nombres largos de archivo?
wnoise
2
Por curiosidad, ¿cuánto tiempo duran los nombres y qué contienen para que Windows no los reconozca?
Bobby

Respuestas:

10

En Debian, Ubuntu y derivados, si ingresa man renameen un símbolo del sistema, obtendrá la página del manual para una utilidad de cambio de nombre que permite que se usen comandos arbitrarios de expresión regular tipo Perl en el cambio de nombre.

Por ejemplo, esto acortará (truncando) todos los archivos en el directorio actual a una longitud de cinco:

rename 's/^(.{5}).*/$1/' *

Funciona capturando los primeros cinco caracteres y luego usándolos en la sustitución, eliminando el resto.

Otro ejemplo es acortar los nombres de archivo (sin extensión) a cinco caracteres mientras se preserva la extensión:

rename 's/^(.{5}).*(\..*)$/$1$2/' *

Captura dos grupos, el primero es los primeros cinco caracteres, el segundo es la extensión. Esto se convertiría myCarefullyCraftedDocument.pdfen myCar.pdf.

Advertencia: Use esto con cuidado, preferiblemente en una copia de su directorio, o haciendo primero copias de seguridad. ¡¡Usted ha sido advertido!! Como mínimo, use rename -nprimero, que le mostrará lo que se haría sin hacerlo realmente.


fuente
1
¿Esto eliminará el prefijo como en PDF? ¿Y qué pasaría con los archivos con el mismo nombre una vez acortados?
Ese ejemplo particular lo hará, sí. Puede escribir una expresión regular para dejar la extensión sola. Actualizaré la respuesta. También protege contra la sobrescritura de archivos que ya existen, por lo que los cambios de nombre posteriores fallarán.
Gracias por su ayuda en esto. Estoy muy agradecido. Tengo un pequeño problema si algunos de los archivos PDF se renombrarán a 5, digamos ¿qué pasaría con los PDF que intenta cambiar el nombre con el mismo nombre? ¿Es una forma en que podemos agregar un número único a todos los que tienen esto? ver abajo ename -n 's / ^ (. {5}). * (\ .. *) $ / $ 1 $ 2 /' * Anexos 123114345234525.pdf renombrado como Annex.pdf Anexos 123114432452352.pdf renombrado como Annex.pdf
@Grimlockz, no creo que puedas poner ese tipo de inteligencia en el cambio de nombre regex. Lo que puede que tenga que hacer es escribir una secuencia de comandos para ajustar el cambio de nombre con ese tipo de inteligencia, y es mejor hacerla como una pregunta por separado para que haya más personas respondiendo que solo yo
@Grimlockz Esta es la razón por la que no quieres hacer todo en una expresión regular. Serás más feliz y mejor escribiendo un script que use expresiones regulares.
Spencer Rathbun
3

Puede mover archivos en conflicto a otro directorio:

for i in *
do
    j=${i:0:16}

    if [ -e "$j" ]
    then
        mv "$i" /path/to/rename/later
    else
        mv "$i" "$j"
    fi
done
kev
fuente
1

Puede escribir un script para acortar los nombres de los archivos y eliminar los caracteres que a Windows no le gustan en unas pocas líneas de bash. Advertencia, código no probado, escrito directamente en mi navegador.

shopt -s dotglob extglob
for x in *; do
  y=${x//+([!-!#$%&'().0-9@A-Z^_`a-z{}~])/_}  # change all problematic characters to _
  if [[ $y = .* ]]; then y=_${y#.}; fi        # change dot files to begin with _
  y=${y:0:16}                                 # truncate names
  y=${y,,}                                    # convert to lowercase
  if [[ -e $y || $y =~ ^(aux|clock\$|com[0-9]|con|lpt[0-9]|nul|prn)(\.*)?$ ]]; then
    # The file exists or is a DOS/Windows reserved name.
    # Change foo.bar to foo~1.bar, foo~2.bar, ... (I ignore the length restriction here)
    i=1
    if [[ $y =~ \. ]]; then
      prefix=${y%%.*}; suffix=.${y#*.}
    else
      prefix=$y; suffix=
    fi
    y=${prefix}~$i$suffix
    while [[ -e $y ]]; do
      ((++i))
      y=${prefix}~$i$suffix
    done
  fi
  mv -- "$x" "$y"
done

Si necesita recurrir a subdirectorios, llame a un script de shell desde find -depth -exec …. O use zsh en lugar de bash; en zsh, se **/*(od)expande a todos los archivos en el directorio actual, de forma recursiva, con archivos anidados más profundamente primero.

Gilles 'SO- deja de ser malvado'
fuente
1

Las secuencias de comandos Shell / python / perl para este tipo de cosas están bien, pero parece que una aplicación gui sería la mejor para usted, por lo que recomendaría pyRenamer , que puede hacer exactamente lo que desea, entre muchas otras cosas (operaciones comunes simples a través de ajustes preestablecidos [eliminando espacios, truncando el nombre de archivo de un punto a otro], búsqueda / reemplazo simple, expresiones regulares complicadas, vista previa, etc.

Su distribución podría incluso tenerla en su repositorio de software (Fedora sí).

rsaw
fuente
0

Algunos sistemas no tienen el renamecomando, así que, como alternativa a la respuesta de paxdiablo, a continuación se explica cómo hacer lo mismo con mv.

for f in *.pdf; do 
    tmp=`echo $f | sed -r 's//^(.{5}).*(\..*)$/$1$2/'`
    mv -b ./"$f" ./"$tmp"
done

La -bbandera en movimiento crea una copia de seguridad de los archivos que serían eliminados o sobrescritos. Al cambiar el patrón global en el bucle for, puede ajustar en qué archivos se ejecuta, utilizándose *solo para ejecutarse en todos los archivos.

Spencer Rathbun
fuente
1
No es necesario usar echoy una tubería (podría ser muy costoso si tiene muchos archivos), use un heredoc o herestring en su lugar.
Chris Down
1
@ChrisDown ver aquí . Según el artículo de la wiki , los procesos canalizados se bifurcan, pero no dice nada sobre cómo ejecutarlos en sus propios shells.
Spencer Rathbun
1
Por ejemplo, observe la diferencia entre eval 'echo $BASH_SUBSHELL'y eval 'echo $BASH_SUBSHELL' | cat.
Chris Down
2
Acabo de hacer una prueba rápida, timeusando un bucle usando echo $i | sedy otro usando sed ... <<<$i, y la hererestring tomó aproximadamente 2/3 del tiempo del eco.
Kevin
1
@SpencerRathbun Sí. <<comienza un <i> doc </i> aquí, que es de varias líneas y requiere delimitadores. <<<crea una <i> cadena </i> aquí, que solo toma una variable / cadena. Probarlo, var=abc // cat<<<$var // cat <<$var.
Kevin
0

Si necesita experimentar con el cambio de nombre de los archivos y tiene las bibliotecas de KDE instaladas en su sistema (o no le importa agregarlas), consulte krename.

Le permite hacer bastantes tareas de cambio de nombre simples directamente con sus herramientas y también permite expresiones regulares para situaciones más complicadas.

Le muestra una vista previa de los archivos renombrados a medida que crea las condiciones de cambio de nombre. También le permite cambiar el nombre de los mismos archivos nuevamente, lo cual es útil si desea hacer algo complicado donde hacerlo en etapas reduciría la complejidad de cada etapa a algo que pueda resolver rápidamente.

Joe
fuente
-1
for file in *; do
    mv "$file" $(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')
done &
Jairo Bernal
fuente