Comment renommer avec préfixe / suffixe?

95

Comment faire mv original.filename new.original.filenamesans retaper le nom de fichier d'origine?

J'imaginerais pouvoir faire quelque chose comme mv -p=new. original.filenameou peut-être mv original.filename new.~ou autre chose - mais je ne vois rien de tel après avoir regardé man mv/ info mvpages.

Bien sûr, je pourrais écrire un script shell pour ce faire, mais n'y a-t-il pas une commande / indicateur existant pour cela?

Peter Boughton
la source

Réponses:

122

Dans Bash et zsh, vous pouvez le faire avec Brace Expansion . Cela élargit simplement une liste d'éléments entre accolades. Par exemple:

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

Vous pouvez donc renommer comme suit:

mv {,new.}original.filename

à mesure que cela s'étend à:

mv original.filename new.original.filename
Dave Webb
la source
Merci, cela semble être la meilleure solution - fonctionne également avec ksh.
Peter Boughton
29
Cela ne fonctionne pas avec des caractères génériques. Autrement dit, dans un répertoire contenant les noms de fichiers a, b, c, l'utilisation de "echo {, new.} *" Donne la liste "abc new. *" (Car la génération de nom de fichier via le développement d'accolades se produit avant de développer les caractères génériques - au moins par inférence).
Jonathan Leffler
Depuis des mois, je cherche une telle solution en utilisant uniquement les fonctionnalités de base du shell ... Je n'aurais jamais proposé quelque chose d'aussi simple, merci beaucoup!
flonk
Merci pour la référence à Brace Expansion :-) exactement ce que je cherchais!
Pim Hazebroek
1
J'adore l'exemple. Je me sens d'humeur à aller à Baskin Robbins pendant ma pause déjeuner maintenant.
Sridhar Sarnobat
156

Vous pouvez utiliser la rename(1)commande:

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

Edit: Si ce renamen'est pas disponible et que vous devez renommer plus d'un fichier, le script shell peut vraiment être court et simple pour cela. Par exemple, pour renommer tous *.jpgà prefix_*.jpgdans le répertoire courant:

for filename in *.jpg; do mv "$filename" "prefix_$filename"; done;
Simon Lehmann
la source
Graphite installé ce week-end, et ils ont une étape qui est essentiellement ("copier tous les fichiers * .example dans le dossier conf, en supprimant le suffixe de l'exemple"). Vraiment paresseux de leur part, mais rename 's/(.*).example/$1/' *.examplem'a sauvé de l'ennui.
Conrad.Dean
2
C'est la meilleure réponse à ce jour.
lifeisfoo
Je ne pense pas que vous ayez besoin du premier $dans ce scénario. Alors juste's/(.*)/new.$1/'
wisbucky
1
renameLa commande ne fonctionne pas sur ma machine RHEL 6. Existe-t-il différentes versions de cette commande? Cela a for ... donefonctionné pour moi.
robsch
25

Vous pouvez obtenir un renommage de plusieurs fichiers compatible Unix (en utilisant des caractères génériques) en créant une boucle for:

for file in *; do
  mv $file new.${file%%}
done
Un Muguro
la source
7
Quelle est la différence entre cela et ce que Simon Lehmann a déjà répondu ?
Peter Boughton
4
Cela fonctionne très bien. Que ${file%%}fais-tu? Semble similaire à simplement $ {file}
Sidmitra
Je suis également curieux de connaître $ {file %%}
Lucas Bustamante
10

J'ai vu des gens mentionner une renamecommande, mais elle n'est pas systématiquement disponible sur les systèmes Unix (contrairement aux systèmes Linux, disons, ou Cygwin - sur les deux, renommer est un exécutable plutôt qu'un script). Cette version de renamea une fonctionnalité assez limitée:

rename from to file ...

Il remplace la partie from des noms de fichier par to , et l'exemple donné dans la page de manuel est:

rename foo foo0 foo? foo??

Cela renomme foo1 en foo01 et foo10 en foo010, etc.

J'utilise un script Perl appelé rename, que j'ai initialement extrait de la première édition du livre Camel, vers 1992, puis étendu, pour renommer les fichiers.

#!/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";
    }
}

Cela vous permet d'écrire n'importe quelle commande de substitution ou de translittération Perl pour mapper les noms de fichiers. Dans l'exemple spécifique demandé, vous utiliseriez:

rename 's/^/new./' original.filename
Jonathan Leffler
la source
Merci, si je pouvais accepter une deuxième réponse, ce serait celle-ci. Je voulais une commande standard comme quelque chose qui fonctionnera simplement sur tout ce que je pourrais utiliser, mais je peux mettre ce script sur les machines que j'utilise fréquemment et cela sera toujours utile.
Peter Boughton
James Wong fait remarquer que pour Arch Linux, vous pouvez simplement télécharger et installer ce script via l' pacmanutilisation: pacman -Sy perl-rename. Ensuite, ajoutez-y un alias dans votre bashrc:alias rename='perl-rename'
Jonathan Leffler
Que faire si "from" ou "to" sont des chaînes vides, c'est-à-dire que vous voulez ajouter quelque chose à chaque nom de fichier ou supprimer quelque chose complètement
Troyseph
1
@Troyseph - pour ajouter '.htmlaux noms de fichiers, utilisez 's/$/.html/'- pour supprimer tmpde partout dans les noms de fichiers, utilisez 's/tmp//g'(rechercher tmpet remplacer par rien partout).
Jonathan Leffler
4

Le moyen le plus simple de renommer en bloc des fichiers dans un répertoire est:

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

S'il est ouvert à une modification, vous pouvez utiliser un suffixe au lieu d'un préfixe. Ensuite, vous pouvez utiliser la complétion par tabulation pour obtenir le nom de fichier d'origine et ajouter le suffixe.

Sinon, ce n'est pas quelque chose qui est pris en charge par la commande mv. Un simple script shell pourrait cependant faire face.

workmad3
la source
Souvent, je veux les deux, mais principalement le préfixe - comme vous le dites, la complétion par tabulation peut gérer les suffixes.
Peter Boughton
1

Dans mon cas, j'ai un groupe de fichiers qui doit être renommé avant de pouvoir travailler avec eux. Chaque fichier a son propre rôle dans le groupe et a son propre modèle.

En conséquence, j'ai une liste de commandes de renommage comme celle-ci:

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

Essayez ceci aussi:

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

Cela produira toutes les combinaisons avec des préfixes et des suffixes:

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

Une autre façon de résoudre le même problème consiste à créer un tableau de mappage et à ajouter le préfixe correspondant pour chaque type de fichier, comme indiqué ci-dessous:

#!/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
la source
1

Renommer en bloc les fichiers script bash

#!/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ő
la source
0

Je sais qu'il y a de bonnes réponses ici, mais je n'ai trouvé aucune référence pour gérer les extensions de nom de fichier lors de l'ajout d'un suffixe.

J'avais besoin d'ajouter le suffixe «_en» à tous les wavfichiers d'un dossier avant l'extension de fichier.

La magie est là: %.*

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

Si vous devez gérer différentes extensions de fichier, cochez cette réponse. Un peu moins intuitif.

yeya
la source