Come rinominare con prefisso / suffisso?


95

Come faccio a fare a mv original.filename new.original.filenamemeno di ridigitare il nome del file originale?

Immagino di poter fare qualcosa di simile mv -p=new. original.filenameo forse mv original.filename new.~o qualsiasi altra cosa, ma non riesco a vedere nulla di simile dopo aver guardato man mv/ info mvpages.

Certo, potrei scrivere uno script di shell per farlo, ma non c'è un comando / flag esistente per questo?

Risposte:


122

In Bash e zsh puoi farlo con Brace Expansion . Questo espande semplicemente un elenco di elementi tra parentesi graffe. Per esempio:

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

Quindi puoi rinominare come segue:

mv {,new.}original.filename

poiché questo si espande a:

mv original.filename new.original.filename

Grazie, questa sembra essere la soluzione migliore - funziona anche con ksh.
Peter Boughton

29
Ciò che questo non fa è lavorare con i caratteri jolly. Cioè, in una directory contenente nomi di file a, b, c, l'utilizzo di "echo {, new.} *" Restituisce l'elenco "abc new. *" (Perché la generazione del nome di file tramite l'espansione delle parentesi graffe avviene prima dell'espansione dei caratteri jolly - almeno per inferenza).
Jonathan Leffler

Da mesi cerco una soluzione del genere utilizzando solo le funzionalità di base della shell ... non avrei mai pensato a qualcosa di così semplice, grazie mille!
flonk

Grazie per il riferimento a Brace Expansion :-) esattamente quello che stavo cercando!
Pim Hazebroek

1
Amo l'esempio. Mi sento dell'umore giusto per andare da Baskin Robbins durante la pausa pranzo adesso.
Sridhar Sarnobat

156

Potresti usare il rename(1)comando:

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

Modifica: se renamenon è disponibile e devi rinominare più di un file, lo scripting della shell può essere davvero breve e semplice per questo. Ad esempio, per rinominare tutte *.jpga prefix_*.jpgnella directory corrente:

for filename in *.jpg; do mv "$filename" "prefix_$filename"; done;

Grafite installata questo fine settimana, e hanno un passaggio che essenzialmente ("copia tutti i file * .example nella cartella conf, rimuovendo il suffisso di esempio"). Davvero pigro da parte loro, ma rename 's/(.*).example/$1/' *.examplemi ha salvato dalla noia.
Conrad.Dean

2
Questa è la migliore risposta finora.
lifeisfoo

Non penso che tu abbia bisogno del primo $in questo scenario. Quindi solo's/(.*)/new.$1/'
wisbucky

1
renameil comando non funziona sulla mia macchina RHEL 6. Esistono versioni differenti di questo comando? Ha for ... donefunzionato per me.
robsch


10

Ho visto persone menzionare un renamecomando, ma non è normalmente disponibile sui sistemi Unix (al contrario dei sistemi Linux, diciamo, o Cygwin - su entrambi i quali rinominare è un eseguibile piuttosto che uno script). Quella versione di renameha una funzionalità piuttosto limitata:

rename from to file ...

Sostituisce la parte from dei nomi dei file con to , e l'esempio fornito nella pagina man è:

rename foo foo0 foo? foo??

Questo rinomina foo1 in foo01 e foo10 in foo010, ecc.

Uso uno script Perl chiamato rename, che originariamente ho estratto dalla prima edizione del libro Camel, intorno al 1992, e poi esteso, per rinominare i file.

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

Ciò consente di scrivere qualsiasi comando Perl sostitutivo o traslitterato per mappare i nomi dei file. Nell'esempio specifico richiesto, useresti:

rename 's/^/new./' original.filename

Grazie, se potessi accettare una seconda risposta sarebbe questa. Volevo un comando standard come qualcosa che funzionasse su qualsiasi cosa potessi usare, ma posso mettere questo script sulle macchine che uso frequentemente e sarà comunque utile.
Peter Boughton

James Wong osserva che per Arch Linux, si può solo scaricare ed installare questo script tramite pacmanutilizzando: pacman -Sy perl-rename. Quindi aggiungi un alias nella tua bashrc:alias rename='perl-rename'
Jonathan Leffler

cosa succede se "da" o "a" sono stringhe vuote, ovvero si desidera aggiungere qualcosa a ciascun nome di file o rimuovere qualcosa completamente
Troyseph

1
@ Troyseph - per aggiungere '.htmlai nomi dei file, usa 's/$/.html/'- per rimuovere tmpda ogni parte i nomi dei file, usa 's/tmp//g'(trova tmpe sostituisci con niente ovunque).
Jonathan Leffler

4

Il modo più semplice per rinominare in blocco i file nella directory è:

ls | xargs -I fileName mv fileName fileName.suffix

2

Se è aperto a una modifica, puoi usare un suffisso invece di un prefisso. Quindi puoi usare il completamento con tabulazione per ottenere il nome del file originale e aggiungere il suffisso.

Altrimenti, no, questo non è qualcosa che è supportato dal comando mv. Un semplice script di shell potrebbe farcela.


Spesso le voglio entrambe, ma principalmente il prefisso: come dici tu, il completamento con tabulazione può gestire i suffissi.
Peter Boughton

1

Nel mio caso ho un gruppo di file che deve essere rinominato prima di poter lavorare con loro. Ogni file ha il proprio ruolo nel gruppo e ha il proprio modello.

Di conseguenza ho un elenco di comandi di rinomina come questo:

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

Prova anche questo:

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

Questo produrrà tutte le combinazioni con prefissi e suffissi:

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

Un altro modo per risolvere lo stesso problema è creare un array di mappatura e aggiungere il prefisso corrispondente per ogni tipo di file come mostrato di seguito:

#!/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

1

Rinomina in blocco i file 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

0

So che ci sono ottime risposte qui, ma non ho trovato alcun riferimento per gestire le estensioni del nome file quando si aggiunge il suffisso.

Avevo bisogno di aggiungere il suffisso "_en" a tutti i wavfile in una cartella prima dell'estensione del file.

La magia è qui: %.*

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

Se devi gestire diverse estensioni di file, controlla questa risposta. Un po 'meno intuitivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.