Il existe plusieurs fichiers dans un répertoire qui commencent par le préfixe fgh
, par exemple:
fghfilea
fghfileb
fghfilec
Je veux tous les renommer pour commencer par le préfixe jkl
. Existe-t-il une seule commande pour faire cela au lieu de renommer chaque fichier individuellement?
Il existe plusieurs manières, mais utiliser rename
sera probablement le plus simple.
Utilisation d'une version de rename
:
rename 's/^fgh/jkl/' fgh*
Utilisation d'une autre version de rename
(identique à réponse de Judy2K ):
rename fgh jkl fgh*
Vous devriez consulter la page de manuel de votre plate-forme pour savoir lequel des cas ci-dessus s'applique.
Voici comment sed
et mv
peuvent être utilisés ensemble pour renommer:
for f in fgh*; do mv "$f" $(echo "$f" | sed 's/^fgh/jkl/g'); done
Comme indiqué ci-dessous, si les noms de fichiers contiennent des espaces, les guillemets peuvent avoir besoin de entourer la sous-fonction qui renvoie le nom pour déplacer les fichiers:
for f in fgh*; do mv "$f" "$(echo $f | sed 's/^fgh/jkl/g')"; done
renommer peut ne pas être dans tous les systèmes. Donc, si vous ne l'avez pas, utilisez Shell Cet exemple dans bash Shell
for f in fgh*; do mv "$f" "${f/fgh/xxx}";done
Utiliser mmv :
mmv "fgh*" "jkl#1"
Il y a plusieurs façons de le faire (toutes ne fonctionneront pas sur tous les systèmes Unixy):
ls | cut -c4- | xargs -I§ mv fgh§ jkl§
Le § peut être remplacé par tout ce qui vous convient. Vous pouvez le faire aussi avec find -exec
mais cela se comporte légèrement différemment sur de nombreux systèmes, aussi j’évite généralement cela
for f in fgh*; do mv "$f" "${f/fgh/jkl}";done
Brut mais efficace comme on dit
rename 's/^fgh/jkl/' fgh*
Vraiment joli, mais renommer n’est pas présent sur BSD, qui est le système unix le plus répandu à ce jour.
rename fgh jkl fgh*
ls | Perl -ne 'chomp; next unless -e; $o = $_; s/fgh/jkl/; next if -e; rename $o, $_';
Si vous insistez pour utiliser Perl, mais qu'il n'y a pas de renommage sur votre système, vous pouvez utiliser ce monstre.
Certaines sont un peu compliquées et la liste est loin d’être exhaustive, mais vous trouverez ici ce que vous voulez pour à peu près tous les systèmes Unix.
rename fgh jkl fgh*
Utiliser find
, xargs
et sed
:
find . -name "fgh*" -type f -print0 | xargs -0 -I {} sh -c 'mv "{}" "$(dirname "{}")/`echo $(basename "{}") | sed 's/^fgh/jkl/g'`"'
C'est plus complexe que la solution de @ nik mais elle permet de renommer les fichiers de manière récursive. Par exemple, la structure,
.
├── fghdir
│ ├── fdhfilea
│ └── fghfilea
├── fghfile\ e
├── fghfilea
├── fghfileb
├── fghfilec
└── other
├── fghfile\ e
├── fghfilea
├── fghfileb
└── fghfilec
serait transformé à cela,
.
├── fghdir
│ ├── fdhfilea
│ └── jklfilea
├── jklfile\ e
├── jklfilea
├── jklfileb
├── jklfilec
└── other
├── jklfile\ e
├── jklfilea
├── jklfileb
└── jklfilec
La clé pour que cela fonctionne avec xargs
est de invoquer le shell à partir de xargs .
Pour installer le script Perl rename :
Sudo cpan install File::Rename
Il y a deux renommés comme mentionné dans les commentaires de la réponse de Stephan202 . Les distributions basées sur Debian ont le renommer Perl . Les distributions RedHat/RPM ont le nom C renommé .
OS X n’en a pas installé par défaut (au moins en 10.8), pas plus que Windows/Cygwin.
Voici un moyen de le faire en utilisant Groovy en ligne de commande:
groovy -e 'new File(".").eachFileMatch(~/fgh.*/) {it.renameTo(it.name.replaceFirst("fgh", "jkl"))}'
Sous Solaris, vous pouvez essayer:
for file in `find ./ -name "*TextForRename*"`; do
mv -f "$file" "${file/TextForRename/NewText}"
done
#!/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
Je recommanderais d'utiliser mon propre script, qui résout ce problème. Il propose également des options pour modifier l’encodage des noms de fichiers et convertir les combinaisons de signes diacritiques en caractères précomposés, un problème que j’ai toujours lorsque je copie des fichiers de mon 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);
}
}
C'était beaucoup plus facile (sur mon Mac) de faire cela en Ruby. Voici 2 exemples:
# 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
Ma version de renommer des fichiers de masse:
for i in *; do
echo "mv $i $i"
done |
sed -e "s#from_pattern#to_pattern#g” > result1.sh
sh result1.sh
Utiliser renamer :
$ renamer --find /^fgh/ --replace jkl * --dry-run
Supprimez l'indicateur --dry-run
une fois que vous êtes satisfait du résultat.
Utilisation de StringSolver tools (windows & Linux bash) qui traitent par exemples:
filter fghfilea ok fghreport ok notfghfile notok; mv --all --filter fghfilea jklfilea
Il commence par calcule un filtre basé sur des exemples, où l'entrée correspond aux noms de fichier et à la sortie (ok et notok, chaînes arbitraires). Si filter avait l'option --auto ou était appelé seul après cette commande, il créerait respectivement un dossier ok
et un dossier notok
et des fichiers Push.
Ensuite, en utilisant le filtre, la commande mv
est un déplacement semi-automatique qui devient automatique avec le modificateur --auto. En utilisant le filtre précédent grâce à --filter, il trouve un mappage de fghfilea
à jklfilea
et l’applique ensuite à tous les fichiers filtrés.
_ {Autres solutions monolignes} _
Il existe d’autres moyens équivalents de faire de même (chaque ligne est l’équivalent), ce qui vous permet de choisir votre méthode préférée.
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"
Solution en plusieurs étapes
Pour rechercher avec soin si les commandes fonctionnent bien, vous pouvez taper les éléments suivants:
filter fghfilea ok
filter fghfileb ok
filter fghfileb notok
et lorsque vous êtes sûr que le filtre est bon, effectuez le premier mouvement:
mv fghfilea jklfilea
Si vous voulez tester et utiliser le filtre précédent, tapez:
mv --test --filter
Si la transformation ne correspond pas à ce que vous souhaitiez (par exemple, même si mv --explain
vous voyez que quelque chose ne va pas), vous pouvez taper mv --clear
pour redémarrer le déplacement des fichiers ou ajouter d'autres exemples mv input1 input2
où input1 et input2 sont d'autres exemples.
Lorsque vous êtes confiant, tapez simplement
mv --filter
et voilà! Tout le renommage est fait en utilisant le filtre.
DISCLAIMER: Je suis co-auteur de ce travail à des fins académiques. Il pourrait également y avoir bientôt une fonctionnalité produisant bash.
J'ai écrit ce script pour rechercher tous les fichiers .mkv en renommant récursivement les fichiers trouvés en .avi. Vous pouvez le personnaliser selon vos besoins. J'ai ajouté d'autres éléments tels que l'obtention du répertoire de fichier, de l'extension, du nom de fichier à partir d'un chemin de fichier, au cas où vous deviez faire référence à quelque chose dans le futur.
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;
Cela a fonctionné pour moi en utilisant regexp:
Je voulais que les fichiers soient renommés comme ceci:
file0001.txt -> 1.txt
ofile0002.txt -> 2.txt
f_i_l_e0003.txt -> 3.txt
en utilisant l'expression rationnelle [a-z | _] + 0 * ([0-9] +.) où ([0-9] +. ) est une sous-chaîne de groupe à utiliser dans la commande de renommage
ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)/, arr) { print arr[0] " " arr[1] }'|xargs -l mv
Produit:
mv file0001.txt 1.txt
mv ofile0002.txt 2.txt
mv f_i_l_e0003.txt 3.txt
Un autre exemple:
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
Produit:
mv file001abc.txt abc1.txt
mv ofile0002abcd.txt abcd2.txt
Attention, soyez prudent.
Une autre extension possible de paramètre :
for f in fgh*; do mv -- "$f" "jkl${f:3}"; done
Un script générique pour exécuter une expression sed
sur une liste de fichiers (combine la solution sed
avec la solution rename
):
#!/bin/sh
e=$1
shift
for f in $*; do
fNew=$(echo "$f" | sed "$e")
mv "$f" "$fNew";
done
Appelez en transmettant au script une expression sed
, puis toute liste de fichiers, comme une version de rename
:
script.sh 's/^fgh/jkl/' fgh*
Vous pouvez également utiliser le script ci-dessous. il est très facile de courir sur un terminal ...
// Renomme plusieurs fichiers à la fois
for file in FILE_NAME*
do
mv -i "${file}" "${file/FILE_NAME/RENAMED_FILE_NAME}"
done
Exemple:-
for file in hello*
do
mv -i "${file}" "${file/hello/JAISHREE}"
done