Hay varios archivos en un directorio que comienzan con el prefijo fgh, por ejemplo:

fghfilea
fghfileb
fghfilec

Quiero cambiar el nombre de todos ellos comienzan con el prefijo jkl. Hay un único comando para hacer que en lugar de cambiar el nombre de cada archivo de forma individual?

InformationsquelleAutor | 2009-07-06

21 Comentarios

  1. 259

    Hay varias maneras, pero el uso de rename será probablemente el más fácil.

    El uso de una versión de cambiar:

    rename 's/^fgh/jkl/' fgh*
    

    Utilizando otra versión de cambiar (igual que Judy2K la respuesta):

    rename fgh jkl fgh*
    

    Usted debe comprobar su plataforma de la página de manual para ver que de lo anterior se aplica.

    • +1 Ni siquiera sabía acerca de cambiar el nombre … Ahora puedo dejar de usar un bucle for con mv y sed … Gracias!
    • Está usted seguro de que esto funcionará? O, ¿mezclar un par de arroyos de tu mente en la misma línea?
    • Funciona en mi máquina (Ubuntu 8.10).
    • Supongo que estás hablando te Stephan202 — Mirando al hombre de la página, realmente no mencionar, expresiones regulares, por lo que podría estar en lo correcto. Aún así parece ser la herramienta adecuada: cambiar el nombre de fgh jkl fgh* realmente debe hacer lo correcto.
    • Cualquiera que sea la forma — cambiar nombre es la respuesta.
    • Wow. estás en lo correcto. El hombre de la página en mi máquina es muy diferente de la que he enlazado… voy a actualizar la respuesta en un segundo. Mis disculpas!
    • Se vincula a un diferente rename luego de mostrar la sintaxis de unixhelp.ed.ac.reino unido/CGI/hombre-cgi?cambiar el nombre de es el otro
    • ahora, por favor, no me diga que usted también tiene un script en perl llamado a cambiar el nombre 🙂
    • Bueno Hasterkun, yo esperaba algo como que dispara Stephan.
    • Yo no entiendo rename todavía. Ahora, yo puedo tener una mirada en ella. Gracias. 🙂
    • sí, Esteban línea en realidad puede ir a la rename hombre de la página. Él debe conservar bajo su respuesta corregido.
    • Gracias a todos por aclarar la situación! (@nik: está escrito en Perl, sí 🙂
    • Nunca me encontré con que antes. Definitivamente no estándar. También en RHEL5 pero no Solaris 10.
    • No está presente en todos los sistemas *nix. No en Max OS X, por una parte, y ningún paquete en fink para conseguirlo. No he mirado en MacPorts.
    • AFAICT, rename parece ser específico de Linux script o de la utilidad. Si usted se preocupa en absoluto acerca de la portabilidad, por favor continúe utilizando sed y bucles o de una línea de script en Perl.
    • brew install rename en OS X 🙂
    • Molesto, el apoyo de expresiones regulares es perl-rename en Arch Linux.
    • Para los interesados, he instalado correctamente el cambio de nombre de la utilidad de Mac OS/X copiando la secuencia de comandos de la fuente a «/usr/bin/cambiar nombre» y asignar permisos de ejecución: tips.webdesign10.com/files/rename.pl.txt Trabajo muy bien. 🙂 Ejecución de los Mavericks en un MacBook Pro Retina.
    • Append-to-nombre de archivo de ejemplo para varios archivos json (Mac brew install rename versión): rename -AFOO *.json cadena Delete ejemplo: rename -DFOO *.json

  2. 104

    Esta es la forma en sed y mv se pueden utilizar juntos para hacer el cambio de nombre:

    for f in fgh*; do mv "$f" $(echo "$f" | sed 's/^fgh/jkl/g'); done
    

    Según el comentario de abajo, si los nombres de archivo que contengan espacios, comillas necesidad de rodean la sub-función que devuelve el nombre para mover los archivos a:

    for f in fgh*; do mv "$f" "$(echo $f | sed 's/^fgh/jkl/g')"; done
    
    • Muy de cerca. Tenga en cuenta que sólo desea hacer coincidir la primera aparición de fgh: ‘s/^fgh/jkl/g’ (El símbolo de intercalación hace toda la diferencia).
    • Sólo en aras de la precisión… Te refieres a «fgh en el principio del nombre», no «la primera aparición de fgh». /^fgh/ coincidirá con «fghi», pero no «efgh».
    • Que fue un error por mi parte (se fija).
    • correcto. Dado que sólo los nombres de archivo que coinciden fgh* se procesan, estas nociones coinciden en este caso en particular. Pero, de hecho, yo podría haber sido más preciso.
    • Gracias. muy útil en mi Mac que no tiene rename instalado por defecto. Sed hace el truco 🙂
    • Si usted no tiene acceso a «cambiar nombre» esto funciona muy bien. El código puede requerir entre comillas si los nombres de archivo de incluir espacios. for f in fgh*; do mv "$f" "$(echo $f | sed 's/^fgh/jkl/g')"; done
    • El rename comando en realidad no funciona. El sed línea de comandos anterior a pesar de que trabajó en el primer intento.
    • Sin las comillas, el cambio de nombre de esta lista de archivos podría producir un error: touch fghfilea fghfileb fghfilec fghfile\ d. Me sugerimos tomar en consideración @DaveNelson comentarios.
    • Supongo que tampoco hay necesidad de que el g modificador si sólo desea partido de la primera aparición.

  3. 70

    cambiar el nombre no podría ser en cada sistema. así que si usted no lo tiene, usar el shell
    en este ejemplo en la shell bash

    for f in fgh*; do mv "$f" "${f/fgh/xxx}";done
    
    • En esta solución, sed comando no es necesario. Este es más simple que @nik la respuesta.
    • xxx representa el reemplazo? en caso de que el cartel original, que habría sido «jkl»
    • La solución más limpia de todas.
    • Tal vez el punto más enfáticamente que este es un Bash extensión que no existe en POSIX sh general o en otros shells.
  4. 36

    Utilizando mmv:

    mmv "fgh*" "jkl#1"
    
    • Wow, esta es una excelente y sencilla la forma de solucionar el problema! Me alegro de que se presentó a mmv, gracias!
    • Gracias!!! Nunca había oído hablar de mmv antes. Acabo de instalar y estado jugando con ella – simple, de gran alcance.
    • si desea cambiar el nombre de lote de forma recursiva uso ; en conjunción con #1. ejemplo: mmv ";fgh*" "#1jkl#2"
    • Solución muy elegante!
    • Exactamente lo que yo necesitaba. La captura de grupos con ‘‘ y llame de nuevo con #1,#2,… EX: mmv «mi show ep 1080p.*» «mi.show.#1.#2» = mi.mostrar.001.avi
    • la solución más adecuada

  5. 19

    Hay muchas formas de hacerlo (no todos, de estos funciona en todos los unixy sistemas):

    • ls | cut -c4- | xargs -I§ mv fgh§ jkl§

      El § puede ser reemplazado por cualquier cosa que encuentre conveniente. Usted puede hacer esto con find -exec demasiado, pero que se comporta sutilmente diferentes en muchos sistemas, por lo que suelen evitar que

    • for f in fgh*; do mv "$f" "${f/fgh/jkl}";done

      Crudo, pero eficaz como dicen

    • rename 's/^fgh/jkl/' fgh*

      Real bastante, pero cambiar el nombre no está presente en BSD, que es la más común de unix sistema afaik.

    • rename fgh jkl fgh*

    • ls | perl -ne 'chomp; next unless -e; $o = $_; s/fgh/jkl/; next if -e; rename $o, $_';

      Si usted insiste en usar Perl, pero no se cambiar el nombre en su sistema, puede utilizar este monstruo.

    Algunos de ellos son un poco complicada y la lista está lejos de ser completa, pero usted encontrará lo que usted quiere aquí para casi todos los sistemas unix.

    • me encanta este tipo de monstruo !
    • sí, todavía tengo un punto débil para perl también 🙂
    • tenga en cuenta que ls de salida no debe ser analizado y/o canaliza
    • El Perl monstruo de aquí pasa a funcionar perfectamente si tiene espacios en sus nombres de archivo.
  6. 13
    rename fgh jkl fgh*
    
    • En mi máquina se produce el error de ‘Bareword «fgh» no se permite mientras que la «estricta subs» en uso en (eval 1) línea 1.’
    • ¿cuál es tu máquina?
    • Ubuntu 8.10 (perl v5.10.0 / 2009-06-26)
    • Tengo el mismo problema, ¿se puede resolver? (7 años después)
    • lo siento, realmente no puedo recordar. (Respuesta lenta debido a las vacaciones.)
    • Terminé la solución de este y ya lo he olvidado cuál era la respuesta
    • No estoy seguro si trolling la posteridad o…
    • No se trata de un Perl comando es un comando de la shell. «Dejar de Perl e inténtelo de nuevo» es la solución a esto!

  7. 8

    Utilizando find, xargs y sed:

    find . -name "fgh*" -type f -print0 | xargs -0 -I {} sh -c 'mv "{}" "$(dirname "{}")/`echo $(basename "{}") | sed 's/^fgh/jkl/g'`"'
    

    Es más complejo de lo que @nik la solución pero permite cambiar el nombre de archivos de forma recursiva. Por ejemplo, la estructura,

    .
    ├── fghdir
    │   ├── fdhfilea
    │   └── fghfilea
    ├── fghfile\ e
    ├── fghfilea
    ├── fghfileb
    ├── fghfilec
    └── other
        ├── fghfile\ e
        ├── fghfilea
        ├── fghfileb
        └── fghfilec
    

    sería transformado a este,

    .
    ├── fghdir
    │   ├── fdhfilea
    │   └── jklfilea
    ├── jklfile\ e
    ├── jklfilea
    ├── jklfileb
    ├── jklfilec
    └── other
        ├── jklfile\ e
        ├── jklfilea
        ├── jklfileb
        └── jklfilec
    

    La clave para hacer que funcione con xargs es invocar la concha de la xargs.

    • Yo iba a publicar algo como esto, pero me hubiera llevado una hora de obtener el derecho de comando
  8. 2

    He aquí una forma de hacerlo usando la línea de comandos Groovy:

    groovy -e 'new File(".").eachFileMatch(~/fgh.*/) {it.renameTo(it.name.replaceFirst("fgh", "jkl"))}'
  9. 2

    En Solaris puede probar:

    for file in `find ./-name "*TextForRename*"`; do 
        mv -f "$file" "${file/TextForRename/NewText}"
    done
    
    • Usted obtener la mitad de un punto por citar los nombres de archivo en del bucle, pero for file in $(find) es fundamentalmente defectuoso y no se puede corregir con cita. Si find devuelve ./file name with spaces obtendrá un for recorrer ./file, name, with, y spaces y ninguna cantidad de citar dentro del bucle ayudará (o incluso de ser necesario).
  10. 2
    #!/bin/sh
    
    #replace all files ended witn .f77 to .f90 in a directory
    
    for filename in *.f77
    do 
        #echo $filename
        #b= echo $filename | cut -d. -f1
        #echo $b    
        mv "${filename}" "${filename%.f77}.f90"    
    done
    
  11. 1

    Utilizando StringSolver herramientas (windows & Linux bash) que el proceso por ejemplos:

    filter fghfilea ok fghreport ok notfghfile notok; mv --all --filter fghfilea jklfilea
    

    Primero calcula un filtro basado en ejemplos, donde la entrada es el nombre del archivo y la salida (aceptar y notok, arbitrarias de las cadenas). Si el filtro tiene la opción –auto o se invoca a solas después de este comando, se crea una carpeta ok y una carpeta notok y empuje archivos respectivamente a ellos.

    A continuación, utilizando el filtro, el mv comando es una semi-automática de mover que se convierte en automático con el modificador –auto. Utilizando el filtro anterior gracias a –filtro, se encuentra con una asignación de fghfilea a jklfilea y, a continuación, se aplica en todos los archivos filtrados.


    Otra línea de soluciones de

    Otras formas equivalentes de hacer lo mismo (cada línea es equivalente), así que usted puede elegir su favorito de la manera de hacerlo.

    filter fghfilea ok fghreport ok notfghfile notok; mv --filter fghfilea jklfilea; mv
    filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter fghfilea "mv fghfilea jklfilea"
    # Even better, automatically infers the file name
    filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter "mv fghfilea jklfilea"
    

    Multi-paso de la solución de

    A encontrar cuidadosamente si los comandos están funcionando bien, puede escribir el siguiente:

    filter fghfilea ok
    filter fghfileb ok
    filter fghfileb notok
    

    y cuando esté seguro de que el filtro está bien, realizar el primer movimiento:

    mv fghfilea jklfilea
    

    Si quieres probar y usar el filtro anterior, escriba:

    mv --test --filter
    

    Si la transformación no es lo que quería (por ejemplo, incluso con mv --explain ves que algo está mal), puede escribir mv --clear para reiniciar mover archivos o agregar más ejemplos mv input1 input2 donde input 1 e input 2 son otros ejemplos

    Cuando está seguro, sólo tienes que escribir

    mv --filter
    

    y voilà! Todo el cambio de nombre se realiza utilizando el filtro.

    DESCARGO de responsabilidad: yo soy un co-autor de este trabajo para fines académicos. También podría ser un bash-producción característica de pronto.

  12. 1

    Fue mucho más fácil (en mi Mac) para hacer esto en Ruby. Aquí hay 2 ejemplos:

    # for your fgh example. renames all files from "fgh..." to "jkl..."
    files = Dir['fgh*']
    
    files.each do |f|
      f2 = f.gsub('fgh', 'jkl')
      system("mv #{f} #{f2}")
    end
    
    # renames all files in directory from "021roman.rb" to "021_roman.rb"
    files = Dir['*rb'].select {|f| f =~ /^[0-9]{3}[a-zA-Z]+/}
    
    files.each do |f|
      f1 = f.clone
      f2 = f.insert(3, '_')
      system("mv #{f1} #{f2}")
    end
    
  13. 1

    Utilizando renamer:

    $ renamer --find /^fgh/--replace jkl * --dry-run
    

    Quitar el --dry-run bandera una vez que estés satisfecho el resultado es correcto.

  14. 1

    Mi versión de cambiar el nombre de archivos masivos:

    for i in *; do
        echo "mv $i $i"
    done |
    sed -e "s#from_pattern#to_pattern#g” > result1.sh
    sh result1.sh
    
    • Me gusta la capacidad para comprobar antes de ejecutar la secuencia de comandos
    • De esta forma se rompe magníficamente en los nombres de archivo que contengan espacios, comillas, o de otros metacaracteres del intérprete de órdenes.
  15. 1

    Yo recomendaría el uso de mi propio script que soluciona este problema. También dispone de opciones para cambiar la codificación de los nombres de archivo, y a convertir la combinación de diacriticals a caracteres precompuestos, un problema que siempre tengo cuando me copia los archivos de mi Mac.

    #!/usr/bin/perl
    
    # Copyright (c) 2014 André von Kugland
    
    # Permission is hereby granted, free of charge, to any person obtaining a
    # copy of this software and associated documentation files (the "Software"),
    # to deal in the Software without restriction, including without limitation
    # the rights to use, copy, modify, merge, publish, distribute, sublicense,
    # and/or sell copies of the Software, and to permit persons to whom the
    # Software is furnished to do so, subject to the following conditions:
    
    # The above copyright notice and this permission notice shall be included in
    # all copies or substantial portions of the Software.
    
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    # DEALINGS IN THE SOFTWARE.
    
    $help_msg =
    "rename.pl, a script to rename files in batches, using Perl
               expressions to transform their names.
    Usage:
        rename.pl [options] FILE1 [FILE2 ...]
    Where options can be:
        -v                      Verbose.
        -vv                     Very verbose.
        --apply                 Really apply modifications.
        -e PERLCODE             Execute PERLCODE. (e.g. 's/a/b/g')
        --from-charset=CS       Source charset. (e.g. \"iso-8859-1\")
        --to-charset=CS         Destination charset. (e.g. \"utf-8\")
        --unicode-normalize=NF  Unicode normalization form. (e.g. \"KD\")
        --basename              Modifies only the last element of the path.
    ";
    
    use Encode;
    use Getopt::Long;
    use Unicode::Normalize 'normalize';
    use File::Basename;
    use I18N::Langinfo qw(langinfo CODESET);
    
    Getopt::Long::Configure ("bundling");
    
    # ----------------------------------------------------------------------------------------------- #
    #                                           Our variables.                                        #
    # ----------------------------------------------------------------------------------------------- #
    
    my $apply = 0;
    my $verbose = 0;
    my $help = 0;
    my $debug = 0;
    my $basename = 0;
    my $unicode_normalize = "";
    my @scripts;
    my $from_charset = "";
    my $to_charset = "";
    my $codeset = "";
    
    # ----------------------------------------------------------------------------------------------- #
    #                                        Get cmdline options.                                     #
    # ----------------------------------------------------------------------------------------------- #
    
    $result = GetOptions ("apply" => $apply,
                          "verbose|v+" => $verbose,
                          "execute|e=s" => \@scripts,
                          "from-charset=s" => $from_charset,
                          "to-charset=s" => $to_charset,
                          "unicode-normalize=s" => $unicode_normalize,
                          "basename" => $basename,
                          "help|h|?" => $help,
                          "debug" => $debug);
    
    # If not going to apply, then be verbose.
    if (!$apply && $verbose == 0) {
      $verbose = 1;
    }
    
    if ((($#scripts == -1)
      && (($from_charset eq "") || ($to_charset eq ""))
      && $unicode_normalize eq "")
      || ($#ARGV == -1) || ($help)) {
      print $help_msg;
      exit(0);
    }
    
    if (($to_charset ne "" && $from_charset eq "")
      ||($from_charset eq "" && $to_charset ne "")
      ||($to_charset eq "" && $from_charset eq "" && $unicode_normalize ne "")) {
      $codeset = langinfo(CODESET);
      $to_charset = $codeset if $from_charset ne "" && $to_charset eq "";
      $from_charset = $codeset if $from_charset eq "" && $to_charset ne "";
    }
    
    # ----------------------------------------------------------------------------------------------- #
    #         Composes the filter function using the @scripts array and possibly other options.       #
    # ----------------------------------------------------------------------------------------------- #
    
    $f = "sub filterfunc() {\n    my $s = shift;\n";
    $f .= "    my $d = dirname($s);\n    my $s = basename($s);\n" if ($basename != 0);
    $f .= "    for ($s) {\n";
    $f .= "        $_;\n" foreach (@scripts);   # Get scripts from '-e' opt. #
    # Handle charset translation and normalization.
    if (($from_charset ne "") && ($to_charset ne "")) {
      if ($unicode_normalize eq "") {
        $f .= "        $_ = encode(\"$to_charset\", decode(\"$from_charset\", $_));\n";
      } else {
        $f .= "        $_ = encode(\"$to_charset\", normalize(\"$unicode_normalize\", decode(\"$from_charset\", $_)));\n"
      }
    } elsif (($from_charset ne "") || ($to_charset ne "")) {
        die "You can't use `from-charset' nor `to-charset' alone";
    } elsif ($unicode_normalize ne "") {
      $f .= "        $_ = encode(\"$codeset\", normalize(\"$unicode_normalize\", decode(\"$codeset\", $_)));\n"
    }
    $f .= "    }\n";
    $f .= "    $s = $d . '/' . $s;\n" if ($basename != 0);
    $f .= "    return $s;\n}\n";
    print "Generated function:\n\n$f" if ($debug);
    
    # ----------------------------------------------------------------------------------------------- #
    #                 Evaluates the filter function body, so to define it in our scope.               #
    # ----------------------------------------------------------------------------------------------- #
    
    eval $f;
    
    # ----------------------------------------------------------------------------------------------- #
    #                  Main loop, which passes names through filters and renames files.               #
    # ----------------------------------------------------------------------------------------------- #
    
    foreach (@ARGV) {
      $old_name = $_;
      $new_name = filterfunc($_);
    
      if ($old_name ne $new_name) {
        if (!$apply or (rename $old_name, $new_name)) {
          print "`$old_name' => `$new_name'\n" if ($verbose);
        } else {
          print "Cannot rename `$old_name' to `$new_name'.\n";
        }
      } else {
        print "`$old_name' unchanged.\n" if ($verbose > 1);
      }
    }
    
    • Tenga en cuenta que link-sólo respuestas se desanime, de MODO que las respuestas deben ser el punto final de una búsqueda de una solución (frente a otra escala de referencias, que tienden a obtener obsoletos con el tiempo). Por favor, considere la adición de un stand-alone sinopsis aquí, manteniendo el vínculo como una referencia.
    • Como se predijo por @kleopatra, en el enlace que ha conseguido stale over time
    • ya no más.
  16. 0

    Esto funcionó para mí con regexp:

    Quería archivos a renombrar como este:

    file0001.txt -> 1.txt
    ofile0002.txt -> 2.txt 
    f_i_l_e0003.txt -> 3.txt
    

    uisg la [a-z|_]+0*([0-9]+.) regexp donde ([0-9]+.) es un grupo de la subcadena a utilizar en el comando cambiar nombre

    ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)/, arr) { print   arr[0]  " "  arr[1] }'|xargs  -l mv
    

    Produce:

    mv file0001.txt 1.txt
    mv ofile0002.txt 2.txt
    mv f_i_l_e0003.txt 3.txt
    

    Otro ejemplo:

    file001abc.txt -> abc1.txt
    ofile0002abcd.txt -> abcd2.txt 
    
    ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)([a-z]+)/, arr) { print   arr[0]  " "  arr[2] arr[1] }'|xargs  -l mv
    

    Produce:

      mv file001abc.txt abc1.txt
      mv ofile0002abcd.txt abcd2.txt 
    

    Advertencia, ten cuidado.

  17. 0

    Escribí este guión de búsqueda para todos .archivos mkv de forma recursiva el cambio de nombre de los archivos encontrados para .avi. Usted puede personalizar a su neeeds. He añadido algunas otras cosas, tales como la obtención de directorio del archivo, extensión de archivo, nombre de una ruta de archivo sólo en caso de que usted necesita para referirse a algo en el futuro.

    find . -type f -name "*.mkv" | while read fp; do 
    fd=$(dirname "${fp}");
    fn=$(basename "${fp}");
    ext="${fn##*.}";
    f="${fn%.*}";
    new_fp="${fd}/${f}.avi"
    mv -v "$fp" "$new_fp" 
    done;
    
  18. 0

    Un genérico de secuencia de comandos para ejecutar una sed expresión en una lista de archivos (combina la sed solución con el cambiar solución):

    #!/bin/sh
    
    e=$1
    shift
    
    for f in $*; do
        fNew=$(echo "$f" | sed "$e")
        mv "$f" "$fNew";
    done
    

    Invocar por el paso de la secuencia de comandos de un sed expresión y, a continuación, la lista de archivos, como una versión de cambiar:

    script.sh 's/^fgh/jkl/' fgh*
    
  19. 0

    También se puede utilizar la siguiente secuencia de comandos. es muy fácil de ejecutar en terminal…

    //Cambiar el nombre de varios archivos a la vez

    for file in  FILE_NAME*
    do
        mv -i "${file}" "${file/FILE_NAME/RENAMED_FILE_NAME}"
    done
    

    Ejemplo:-

    for file in  hello*
    do
        mv -i "${file}" "${file/hello/JAISHREE}"
    done
    

Dejar respuesta

Please enter your comment!
Please enter your name here