¿Cómo cambiar el nombre con prefijo / sufijo?

95

¿Cómo lo hago mv original.filename new.original.filenamesin volver a escribir el nombre del archivo original?

Me imagino poder hacer algo como mv -p=new. original.filenameo quizás mv original.filename new.~o lo que sea, pero no puedo ver nada como esto después de mirar man mv/ info mvpages.

Por supuesto, podría escribir un script de shell para hacer esto, pero ¿no existe un comando / indicador existente para ello?

Peter Boughton
fuente

Respuestas:

122

En Bash y zsh puedes hacer esto con Brace Expansion . Esto simplemente expande una lista de elementos entre llaves. Por ejemplo:

# echo {vanilla,chocolate,strawberry}-ice-cream
vanilla-ice-cream chocolate-ice-cream strawberry-ice-cream

Entonces puede cambiar el nombre de la siguiente manera:

mv {,new.}original.filename

ya que esto se expande a:

mv original.filename new.original.filename
Dave Webb
fuente
Gracias, esta parece ser la mejor solución; también funciona con ksh.
Peter Boughton
29
Lo que esto no hace es trabajar con comodines. Es decir, en un directorio que contiene los nombres de archivo a, b, c, el uso de "echo {, new.} *" Produce la lista "abc new. *" (Porque la generación del nombre de archivo a través de la expansión de llaves ocurre antes de expandir los caracteres comodín, al menos por inferencia).
Jonathan Leffler
Desde hace meses estoy buscando una solución de este tipo utilizando solo la funcionalidad básica de shell ... Nunca se me hubiera ocurrido algo tan simple, ¡muchas gracias!
flonk
Gracias por la referencia a Brace Expansion :-) ¡exactamente lo que estaba buscando!
Pim Hazebroek
1
Amo el ejemplo. Ahora tengo ganas de ir a Baskin Robbins durante la pausa para el almuerzo.
Sridhar Sarnobat
156

Podrías usar el rename(1)comando:

rename 's/(.*)$/new.$1/' original.filename

Editar: si renameno está disponible y tiene que cambiar el nombre de más de un archivo, las secuencias de comandos de shell pueden ser realmente cortas y simples para esto. Por ejemplo, para cambiar el nombre de todos *.jpga prefix_*.jpgen el directorio actual:

for filename in *.jpg; do mv "$filename" "prefix_$filename"; done;
Simon Lehmann
fuente
Grafito instalado este fin de semana, y tienen un paso que es esencialmente ("copiar todos los archivos * .example en la carpeta conf, eliminando el sufijo de ejemplo"). Realmente perezoso por su parte, pero rename 's/(.*).example/$1/' *.exampleme salvó del tedio.
Conrad.Dean
2
Esta es la mejor respuesta hasta ahora.
lifeisfoo
No creo que necesites el primero $en este escenario. Así que solo's/(.*)/new.$1/'
wisbucky
1
renameEl comando no funciona en mi máquina RHEL 6. ¿Existen diferentes versiones de este comando? El for ... donetrabajó para mí.
robsch
25

Puede lograr un cambio de nombre de archivos múltiples compatible con Unix (usando comodines) creando un bucle for:

for file in *; do
  mv $file new.${file%%}
done
Un Muguro
fuente
7
¿Cuál es la diferencia entre esto y lo que ya respondió Simon Lehmann ?
Peter Boughton
4
Esto funciona muy bien. ¿Qué ${file%%}haces? Parece similar a simplemente $ {file}
Sidmitra
También tengo curiosidad por $ {file %%}
Lucas Bustamante
10

He visto a personas mencionar un renamecomando, pero no está disponible de forma rutinaria en los sistemas Unix (a diferencia de los sistemas Linux, por ejemplo, o Cygwin; en ambos, el cambio de nombre es un ejecutable en lugar de un script). Esa versión de renametiene una funcionalidad bastante limitada:

rename from to file ...

Sustituye a la de la parte de los nombres de archivo con el que , y el ejemplo dado en la página del manual es:

rename foo foo0 foo? foo??

Esto cambia el nombre de foo1 a foo01, y foo10 a foo010, etc.

Yo uso un script de Perl llamado rename, que originalmente saqué de la primera edición del libro de Camel, alrededor de 1992, y luego se extendió, para renombrar archivos.

#!/bin/perl -w
#
# @(#)$Id: rename.pl,v 1.7 2008/02/16 07:53:08 jleffler Exp $
#
# Rename files using a Perl substitute or transliterate command

use strict;
use Getopt::Std;

my(%opts);
my($usage) = "Usage: $0 [-fnxV] perlexpr [filenames]\n";
my($force) = 0;
my($noexc) = 0;
my($trace) = 0;

die $usage unless getopts('fnxV', \%opts);

if ($opts{V})
{
    printf "%s\n", q'RENAME Version $Revision: 1.7 $ ($Date: 2008/02/16 07:53:08 $)';
    exit 0;
}
$force = 1 if ($opts{f});
$noexc = 1 if ($opts{n});
$trace = 1 if ($opts{x});

my($op) = shift;
die $usage unless defined $op;

if (!@ARGV) {
    @ARGV = <STDIN>;
    chop(@ARGV);
}

for (@ARGV)
{
    if (-e $_ || -l $_)
    {
        my($was) = $_;
        eval $op;
        die $@ if $@;
        next if ($was eq $_);
        if ($force == 0 && -f $_)
        {
            print STDERR "rename failed: $was - $_ exists\n";
        }
        else
        {
            print "+ $was --> $_\n" if $trace;
            print STDERR "rename failed: $was - $!\n"
                unless ($noexc || rename($was, $_));
        }
    }
    else
    {
        print STDERR "$_ - $!\n";
    }
}

Esto le permite escribir cualquier comando sustituto o transliterado de Perl para asignar nombres de archivo. En el ejemplo específico solicitado, usaría:

rename 's/^/new./' original.filename
Jonathan Leffler
fuente
Gracias, si pudiera aceptar una segunda respuesta, sería esta. Quería un comando estándar como algo que simplemente funcionara en cualquier cosa que pudiera usar, pero puedo poner este script en las máquinas que uso con frecuencia y seguirá siendo útil.
Peter Boughton
James Wong señala que para Arch Linux, usted podría descargar e instalar este script mediante pacmanel uso de: pacman -Sy perl-rename. Luego agregue un alias en su bashrc:alias rename='perl-rename'
Jonathan Leffler
¿Qué
pasa
1
@Troyseph: para agregar '.htmla los nombres de los archivos, use 's/$/.html/'- para eliminar tmpde todos los nombres de los archivos, use 's/tmp//g'(busque tmpy reemplace con nada en todas partes).
Jonathan Leffler
4

La forma más sencilla de cambiar el nombre de los archivos de forma masiva en el directorio es:

ls | xargs -I fileName mv fileName fileName.suffix
Brajan Elektro
fuente
2

Si está abierto a una modificación, puede usar un sufijo en lugar de un prefijo. Luego, puede usar la función de tabulación para obtener el nombre de archivo original y agregar el sufijo.

De lo contrario, no, esto no es algo que sea compatible con el comando mv. Sin embargo, un script de shell simple podría hacer frente.

workmad3
fuente
A menudo quiero ambos, pero principalmente el prefijo; como usted dice, la finalización de tabulación puede manejar sufijos.
Peter Boughton
1

En mi caso, tengo un grupo de archivos que es necesario cambiar de nombre antes de poder trabajar con ellos. Cada archivo tiene su propia función en el grupo y tiene su propio patrón.

Como resultado, tengo una lista de comandos de cambio de nombre como este:

f=`ls *canctn[0-9]*`   ;  mv $f  CNLC.$f
f=`ls *acustb[0-9]*`   ;  mv $f  CATB.$f
f=`ls *accusgtb[0-9]*` ;  mv $f  CATB.$f
f=`ls *acus[0-9]*`     ;  mv $f  CAUS.$f

Prueba esto también:

f=MyFileName; mv $f {pref1,pref2}$f{suf1,suf2}

Esto producirá todas las combinaciones con prefijos y sufijos:

pref1.MyFileName.suf1
...
pref2.MyFileName.suf2

Otra forma de resolver el mismo problema es crear una matriz de mapeo y agregar el prefijo corresponsal para cada tipo de archivo como se muestra a continuación:

#!/bin/bash
unset masks
typeset -A masks
masks[ip[0-9]]=ip
masks[iaf_usg[0-9]]=ip_usg
masks[ipusg[0-9]]=ip_usg
...
for fileMask in ${!masks[*]}; 
do  
registryEntry="${masks[$fileMask]}";
fileName=*${fileMask}*
[ -e ${fileName} ] &&  mv ${fileName} ${registryEntry}.${fileName}  
done
aprodan
fuente
1

Cambio de nombre masivo de archivos bash script

#!/bin/bash
# USAGE: cd FILESDIRECTORY; RENAMERFILEPATH/MultipleFileRenamer.sh FILENAMEPREFIX INITNUMBER
# USAGE EXAMPLE: cd PHOTOS; /home/Desktop/MultipleFileRenamer.sh 2016_
# VERSION: 2016.03.05.
# COPYRIGHT: Harkály Gergő | mangoRDI (https://wwww.mangordi.com/) 

# check isset INITNUMBER argument, if not, set 1 | INITNUMBER is the first number after renaming
if [ -z "$2" ]
    then i=1;
else
    i=$2;
fi

# counts the files to set leading zeros before number | max 1000 files
count=$(ls -l * | wc -l)
if [ $count -lt 10 ]
    then zeros=1;
else
    if [ $count -lt 100 ]
        then zeros=2;
    else
        zeros=3
    fi
fi

# rename script
for file in *
do
    mv $file $1_$(printf %0"$zeros"d.%s ${i%.*} ${file##*.})
    let i="$i+1"
done
Harkály Gergő
fuente
0

Sé que hay excelentes respuestas aquí, pero no encontré ninguna referencia para manejar las extensiones de nombre de archivo al agregar el sufijo.

Necesitaba agregar el sufijo '_en' a todos los wavarchivos en una carpeta antes de la extensión del archivo.

La magia esta aqui: %.*

for filename in *.wav; do mv $filename ${filename%.*}_en.wav; done;

Si necesita manejar diferentes extensiones de archivo, verifique esta respuesta. Un poco menos intuitivo.

yeya
fuente