Linux: renommer le fichier mais garder l'extension?

Dans Windows / DOS, je peux dire rename myfile.* yourfile.* Pour changer le nom mais garder l'extension. Comment cela se fait-il sur Linux?

La page man suggère uniquement comment changer l'extension, mais c'est le contraire de ce que je veux.

Prime:
Je souhaite effectivement mettre la date de création d'une photo dans son nom de fichier, pour obtenir quelque chose comme 20091231 2359 New Year.jpg . Je crains que j'ai besoin d'une combinaison de commandes non trivial pour y parvenir?

Voici une réponse pour la question bonus.

Je souhaite effectivement mettre la date de création d'une photo dans son nom de fichier, pour obtenir quelque chose comme 20091231 2359 New Year.jpg. Je crains que j'ai besoin d'une combinaison de commandes non trivial pour y parvenir?

En supposant que vous souhaitez prendre la date de création de la photo à partir des données EXIF, vous aurez besoin d'un outil distinct pour cela. Heureusement, il s'avère que jhead offre un moyen trivial de faire exactement ce que vous voulez, avec son option -n .

 $ jhead -h [...] -n[format-string] Rename files according to date. Uses exif date if present, file date otherwise. If the optional format-string is not supplied, the format is mmdd-hhmmss. If a format-string is given, it is is passed to the 'strftime' function for formatting In addition to strftime format codes: '%f' as part of the string will include the original file name [...] 

Voici un exemple:

 $ jhead -n%Y-%m-%d-%f New_year.jpg New_year.jpg --> 2009-12-31-New_year.jpg 

Edit : Bien sûr, pour ce faire pour un tas de photos, ce serait quelque chose comme:

 $ for i in *jpg; do jhead -n%Y-%m-%d-%f $i; done 

Pour modifier le formatage de la date à votre convenance, regardez la sortie de la date --help , par exemple; Il énumérera les codes de format disponibles.

(Jhead est largement disponible pour différents systèmes. Si vous êtes par exemple sur Ubuntu ou Debian, tapez simplement sudo apt-get install jhead pour l'installer.)

Pour la seule partie renommage, le programme "renommer" fonctionnera. C'est la même chose que l'exemple que vous avez vu dans la page man, tout simplement changé.

 justin@eee:/tmp/q$ touch myfile.{a,b,c,d} justin@eee:/tmp/q$ ls myfile.a myfile.b myfile.c myfile.d justin@eee:/tmp/q$ rename -vs/myfile/yourfile/ myfile.* myfile.a renamed as yourfile.a myfile.b renamed as yourfile.b myfile.c renamed as yourfile.c myfile.d renamed as yourfile.d justin@eee:/tmp/q$ ls yourfile.a yourfile.b yourfile.c yourfile.d justin@eee:/tmp/q$ 
 betelgeuse:tmp james$ ls myfile.* yourfile.* ls: yourfile.*: No such file or directory myfile.a myfile.b betelgeuse:tmp james$ for file > in myfile.* > do > mv "${file}" "`echo $file | sed 's/myfile\./yourfile./'`" > done betelgeuse:tmp james$ ls myfile.* yourfile.* ls: myfile.*: No such file or directory yourfile.a yourfile.b 

La clé est que, si vous avez vu un exemple qui montre comment munir une partie du nom de fichier avec un regex, c'est le seul exemple dont vous avez besoin. Les extensions n'ont aucun statut spécial sur les systèmes de fichiers Unix: elles ne constituent qu'une partie du nom de fichier qui se produit après une . personnage.

Voici quelques autres façons différentes de manipuler les noms de fichiers

 for f in *.jpg do mv "$f" "before_part${f%.*}after_part.${f##*.}" # OR mv "$f" "before_part$(basename "$f" ".jpg")after_part.jpg" done 

Les extensions de paramètres dans la commande mv fonctionnent comme suit:

${f%.*} – Supprimez le modèle correspondant le plus court à partir de la fin de la chaîne contenue dans $f , supprimez ainsi tout après le dernier point inclus. Le % unique signifie "le plus court de la fin".

${f##*.} – Supprimez le plus long motif correspondant du début de la chaîne contenue dans $f , dans ce cas tout avant et avant le dernier point (ceci inclut tous les autres points également). Le double # ( ## ) signifie "le plus long depuis le début".

Donc, par exemple, si $f contient "Foo.bar.baZ.jpg":

 echo "${f%.*}" 

Donne

 Foo.bar.baZ 

et

 echo "${f##*.}" 

Donne

 jpg 

La commande mv , une fois étendue, ressemblerait à:

 mv "Foo.bar.baZ.jpg" "before_partFoo.bar.baZafter_part.jpg" 

Il n'y a pas d'extension de nom de fichier dans Linux.

Utilisez des expressions régulières pour couper des sous-chaînes particulières à partir du nom de fichier et les accéder.

Exemple:

Scène de vie réelle: vous extrayez html à partir d'un fichier chm. Les noms de fichiers dans Windows sont insensibles à la casse, donc, dans Linux, vous obtiendrez des liens brisés. Vous avez un fichier nommé index.HTML , mais href = "index.html" dans les URL. Donc, votre objectif est d'adapter les noms de fichiers pour faire correspondre les liens vers eux.

Supposons que vous avez le nom de fichier dans une variable:

 FILENAME='index.HTML' 

À partir de la version 3.0, bash prend en charge les expressions régulières elles-mêmes, de sorte qu'il n'est pas nécessaire d'utiliser d'autres outils comme grep / sed / perl etc pour effectuer des manipulations de chaînes. L'exemple suivant illustre le remplacement d'une correspondance back-end dans une chaîne:

 echo ${FILENAME/%\.HTML/.html} 

Les chaînes de correspondance et de remplacement peuvent être paramétrées si vous le souhaitez, cela offre une flexibilité supplémentaire lors de l'écriture du script. L'extrait de code suivant atteint le même objectif:

 match='\.HTML' replacement='.html' echo ${FILENAME/%$match/$replacement} 

Consultez les documents bash pour plus d'informations.

Voici un autre:

 find -name "*.jpg" -printf '"%p" "%h/%TY%Tm%Td %TH%TM %f"\n' | while read -rf do eval "mv ${f}" done 

Il y a toujours plus d'une façon de le faire. J'ai mis le script suivant comme / usr / local / bin / mrename.

Ensuite, dans le script contenant les fichiers photo, tapez simplement: mrename

Il existe également une fonctionnalité de commentaire facultatif dans le script pour l'échelle des photos (à l'aide d'ImageMagick).

J'espère que cela est utile pour certaines personnes.

 #!/usr/bin/perl # # mrename files # # use strict; # if no 2 args, use defaults my $dir = "."; # read in path from command line $dir = $ARGV[0] if ( defined( $ARGV[0] ) && $ARGV[0] ne "" ); # read in directory contents opendir( DIR, $dir ); my @files = readdir( DIR ); closedir( DIR ); # rename and/or scale each file in directory my $number_of_files = scalar( @files ); my $curfile = 0; foreach my $file( @files ) { # only rename and scale jpg/gif files if ( $file =~ /\w+\.(jpg)$/ ) { my $extension = $1; $extension =~ tr/AZ/az/; my $full_filename = "$dir/$file"; # get stats on file- specifically the last modified time (my $dev,my $ino,my $mode,my $nlink,my $uid,my $gid,my $rdev,my $size, my $atime,my $mtime,my $ctime,my $blksize,my $blocks) = stat($full_filename); # convert last-modified time from seconds to practical datetime terms (my $sec,my $min,my $hour,my $mday,my $mon,my $year,my $wday,my $yday, my $isdst) = localtime($mtime); ++$mon; $year += 1900; my $filecdate = sprintf( "m%04i%02i%02i_%02i%02i%02i.$extension", $year, $mon, $mday, $hour, $min, $sec ); my $full_newfilename = "$dir/$filecdate"; # to scale files, use imagemagick by using the command below instead of mv #my $cmd = "convert $full_filename -resize $scale% $full_newfilename"; my $cmd = "mv $full_filename $full_newfilename"; system( $cmd ); # update percentage done my $percent_done = sprintf( "%5.2lf", 100* (++$curfile) / $number_of_files ); print "\r$percent_done%"; } } print "\n";