Je dois renommer env. 70 000 fichiers. Par exemple: de sb_606_HBO_DPM_0089000
à sb_606_dpm_0089000
etc.
La plage de numéros va de 0089000
à 0163022
. Ce n'est que la première partie du nom qui doit changer. tous les fichiers sont dans un seul répertoire et sont numérotés séquentiellement (une séquence d'images). Les chiffres doivent rester inchangés.
Quand j'essaye ceci dans bash, cela me fait peur que la 'liste d'arguments soit trop longue'.
Éditer:
J'ai d'abord essayé de renommer un seul fichier avec mv
:
mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx
Ensuite, j'ai essayé de renommer une plage (j'ai appris ici la semaine dernière comment déplacer une charge de fichiers, j'ai donc pensé que la même syntaxe pourrait fonctionner pour renommer les fichiers ...). Je pense que j'ai essayé ce qui suit (ou quelque chose comme ça):
mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx
la source
ARG_MAX
limite du shell . Comme cette question demande explicitement une solution en ligne de commande, les solutions GUI (éventuellement égales) comme dans l'autre question ne correspondent pas non plus.mv {1..2} {3..4}
cela ne fonctionne pas, ce qui est un tout autre problème queARG_MAX
... Tous ceux qui ont répondu ressentiront probablement la même chose! Donc, de mon point de vue, j'aimerais que vous annuliez votre dernière édition et, si vous le souhaitez, posez une toute nouvelle question sur l'mv
ing avec les plagesargument list too long
erreur. Il n'est pas nécessaire de clarifier davantage, ce n'est clairement pas une dupe, car nous avons besoin d'une solution de contournement pour traiter ARG_MAX et les réponses dans le doublon proposé ne le font pas.Réponses:
Une façon consiste à utiliser
find
avec-exec
et l'+
option. Cela construit une liste d'arguments, mais divise la liste en autant d'appels que nécessaire pour opérer sur tous les fichiers sans dépasser la liste d'arguments maximale. Il convient lorsque tous les arguments seront traités de la même manière. C'est le cas avecrename
, mais pas avecmv
.Vous devrez peut-être installer Perl renommer:
Ensuite, vous pouvez utiliser, par exemple:
Supprimez
-n
après le test pour renommer les fichiers.la source
Je vais proposer trois alternatives. Chacun est une simple commande sur une seule ligne, mais je fournirai des variantes pour les cas plus compliqués, principalement au cas où les fichiers à traiter sont mélangés avec d'autres fichiers dans le même répertoire.
mmv
J'utiliserais la commande mmv du package du même nom :
Notez que les arguments sont passés sous forme de chaînes, donc l'expansion glob ne se produit pas dans le shell. La commande reçoit exactement deux arguments, puis trouve les fichiers correspondants en interne, sans limites strictes sur le nombre de fichiers. Notez également que la commande ci-dessus suppose que tous les fichiers qui correspondent au premier glob doivent être renommés. Bien sûr, vous êtes libre d'être plus précis:
Si vous avez des fichiers en dehors de la plage de numéros demandée dans le même répertoire, vous pourriez être mieux avec la boucle sur les numéros donnés plus bas dans cette réponse. Cependant, vous pouvez également utiliser une séquence d'invocations mmv avec des modèles appropriés:
boucle sur les nombres
Si vous voulez éviter d'installer quoi que ce soit, ou devez sélectionner par plage de numéros en évitant les correspondances en dehors de cette plage, et que vous êtes prêt à attendre 74 023 appels de commandes, vous pouvez utiliser une boucle bash simple:
Cela fonctionne particulièrement bien ici car il n'y a pas de lacunes dans la séquence. Sinon, vous souhaiterez peut-être vérifier si le fichier source existe réellement.
Notez que contrairement à
for ((i=89000; i<=163022; ++i))
l'expansion d'accolade, il gère les zéros en tête depuis la sortie de certains Bash il y a quelques années. En fait, un changement que j'ai demandé, donc je suis heureux de voir des cas d'utilisation pour cela.Pour en savoir plus: Brace Expansion dans les pages d'informations de Bash, en particulier la partie sur
{x..y[..incr]}
.boucler sur des fichiers
Une autre option serait de boucler sur un glob approprié, au lieu de simplement boucler sur la plage entière en question. Quelque chose comme ça:
Encore une fois, il s'agit d'une seule
mv
invocation par fichier. Et encore une fois, la boucle est sur une longue liste d'éléments, mais la liste entière n'est pas passée en argument à un sous-processus, mais gérée en interne par bash, donc la limite ne vous causera pas de problèmes.Pour en savoir plus: Shell Parameter Expansion dans les pages d'informations de Bash, documentant
${parameter/pattern/string}
entre autres.Si vous souhaitez restreindre la plage de numéros à celle que vous avez fournie, vous pouvez ajouter une vérification pour cela:
Ici ,
${i##pattern}
supprime le plus long préfixe correspondantpattern
de$i
. Ce préfixe le plus long est défini comme n'importe quoi, puis un trait de soulignement, puis zéro ou plusieurs zéros. Ce dernier est écrit comme*(0)
ce qui est une extension modèle de glob qui dépend de l'extglob
option définie. La suppression des zéros de tête est importante pour traiter le nombre comme base 10 et non base 8. L'+([0-9])
argument dans la boucle est un autre glob étendu, correspondant à un ou plusieurs chiffres, juste au cas où vous auriez des fichiers qui commencent de la même manière mais ne se terminent pas par un nombre.la source
Une façon de contourner la
ARG_MAX
limite est d'utiliser la fonction intégrée du shell bashprintf
:Ex.
mais
la source
find
dans le répertoire actuel.
pour tous les fichiers-type f
et renommez le fichier trouvé$1
en le remplaçantHBO_DPM
pardmp
un par un-exec ... \;
remplacer
echo
parmv
pour effectuer le changement de nom.la source
Vous pouvez écrire un petit script python, quelque chose comme:
Enregistrez-le en tant que fichier texte comme
rename.py
dans le dossier dans lequel se trouvent les fichiers, puis avec le terminal dans ce dossier:la source
Vous pouvez le faire fichier par fichier (cela peut prendre un certain temps) avec
Comme le Perl
rename
utilisé dans d'autres réponses,rename.ul
a également une option-n
ou--no-act
pour les tests.la source
-n
drapeau que j'ai utilisé pour les tests et suggérant qu'il pouvait également être utilisérename.ul
.Je vois que personne n'a invité mon meilleur ami
sed
à la fête :). Lafor
boucle suivante atteindra votre objectif:Il existe de nombreux outils pour un tel travail, sélectionnez celui qui vous convient le mieux. Celui-ci est simple et facilement modifié pour convenir à cela ou à d'autres fins ...
la source
$i
dans la substitution de commande, mais pas un moyen facile de gérer un saut de ligne en fin de fichier.Puisque nous proposons des options, voici une approche Perl.
cd
dans le répertoire cible et exécutez:Explication
perl -e
: lance le script donné par-e
.foreach(glob){}
: exécuter ce qui se trouve{ }
sur chaque résultat du glob.glob("sb_*")
: retourne une liste de tous les fichiers et répertoires du répertoire courant dont les noms correspondent au glob du shellsb*
.rename $_, s/_HBO_DPM_/_dpm_/r
: perl magic.$_
est une variable spéciale qui contient chaque élément sur lequel nous itérons (dans leforeach
). Alors ici, ce sera chaque fichier trouvé.s/_HBO_DPM_/_dpm_/
remplace la première occurrence de_HBO_DPM_
avec_dpm_
. Il s'exécute$_
par défaut, il s'exécutera donc sur chaque nom de fichier. Les/r
moyens « appliquent ce remplacement à une copie de la chaîne cible (le nom du fichier) et retourner la chaîne modifiée.rename
Est -ce que ce que vous attendez: il Renomme les fichiers Donc tout cela va renommer le nom du fichier en cours (.$_
À lui - même) avec_HBO_DPM_
remplacé par_dpm_
.Vous pouvez écrire la même chose qu'un script développé (et plus lisible):
la source
Selon le type de changement de nom que vous envisagez, utilisez vidir avec l' de plusieurs lignes peut être satisfaisante.
Dans votre cas particulier, vous pouvez sélectionner toutes les lignes dans votre éditeur de texte et supprimer la partie _ " HBO" des noms de fichiers en quelques touches.
la source
vidir
?