Comment renommer plusieurs fichiers en remplaçant la chaîne dans le nom du fichier? cette chaîne contient un "#"

43

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-certain-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

Ces articles mentionnés ont tous répondu à ma question. Cependant, aucun d'entre eux ne fonctionne pour moi. Je suppose que c'est parce que la chaîne que je tente de remplacer contient un #. Y a-t-il un moyen spécial de résoudre ce problème?

J'ai un fichier image qui a été remplacé par # U00a9 lors d'une migration de site. Celles-ci ressemblent à ceci:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

et je veux le changer en quelque chose comme ceci:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

MISE À JOUR:

Ces exemples commencent tous par "LU00a9ucky mais voici de nombreuses images avec des noms différents. Je cible simplement la partie" # U00a9 "de la chaîne à remplacer par" safe ".

Communauté
la source
3
Alors qu'as-tu réellement essayé? Je vois que vous avez lié à quelques questions et dites qu'elles ont échoué, mais comment ont-elles échoué? OMI le meilleur exemple utilise la renamecommande. Je soupçonne que votre changement de nom serait aussi simple que rename -n 's/#/safeNBC/' *.jpg.
Zoredache
J'ai essayé rename -n 's/#U00a9/safe/' *.jpget la commande a été acceptée mais aucun changement ne s'est produit.
Bien sûr, comme vous l'avez vu dans la documentation que vous avez sûrement examinée, -nc'est l' no actoption. Ce qui vous permet de voir si cela fonctionne avant de l'utiliser. Le résultat affiché à l'écran indique-t-il correctement les nouveaux noms potentiels?
Zoredache
Je m'excuse d'avoir copié et collé votre exemple sans y accorder toute votre attention. J'ai exécuté la commande de changement de nom sans le -n. Je crois que @DTK a résolu le problème, je n’échappais pas au #.
Remplacement des chaînes dans les noms de fichiers sous MacOS: superuser.com/questions/152627/…
Anton Tarasenko

Réponses:

65

Pour remplacer #par les somethingelsenoms de fichiers dans le répertoire actuel (non récursif), vous pouvez utiliser l' utilitaire de renommage GNU :

rename  's/#/somethingelse/' *

Des personnages comme -doit être échappé avec un \.

Pour votre cas, vous voudriez utiliser

rename 's/#U00a9/safe/g' *

Notez que si vous ne souhaitez utiliser qu'une sélection de fichiers, par exemple uniquement *.jpg, ajustez l'entrée finale pour qu'elle corresponde à cette sélection:

rename 's/#U00a9/safe/g' *.jpg

Pour effectuer un test avant de changer les noms de fichiers, utilisez l' -nindicateur:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

Pour OS X, GNU renommage peut être installé à l' aide homebrew : brew install rename.

KrisWebDev
la source
Cela n'a pas fonctionné sur ma machine (Arch Linux), mais la réponse de mik l'a fait.
Marcvangend
@marcvangend Quelle version de renameutilisez-vous? # sudo pacman -S perl-renameinstallera la version perl, qui est plus puissante et qui suffira peut-être pour que cette réponse fonctionne pour vous.
John Gowers
@ JohnGowers Merci! Je n'avais pas réalisé qu'il y avait deux versions. Sur mon système, rename --versionretourne rename from util-linux 2.29.2donc ce n'est effectivement pas la version Perl.
Marcvangend
5
Il existe deux renameutilitaires communs, mais aucun d'entre eux n'est développé par GNU: les distributions basées sur Debian incluent un renameutilitaire avec leur paquet Perl, tandis que les distributions basées sur Red Hat utilisent l' renameutilitaire de l' util-linuxorganisation du noyau Linux. Votre lien est avec la fonctionrename C de la bibliothèque standard GNU.
Anthony G - justice pour Monica le
2
Dans cette réponse, pourquoi nous devons écrire /genrename 's/#U00a9/safe/g' *
Nikhil
24

trouver la liste des fichiers puis remplacer le mot clé. ci-dessous est un exemple

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;
Sujit Dhamale
la source
1
Vous avez besoin de guillemets autour de vos mvarguments, au cas où il y aurait des espaces dans le nom
Stop Harming Monica
Je devais remplacer tous les fichiers * _spec.rb par * _controller_spec.rb et votre solution a fonctionné pour moi. Merci
Jedi
Merci. Cela résoudra mon problème
Fabio Souza
19

Ce n'est pas difficile, assurez-vous simplement d'échapper l'octothorpe (#) dans le nom en ajoutant une barre oblique inversée (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 
Communauté
la source
Votre explication est logique, en évitant les #sons comme ce dont j'avais besoin. Je ne vois pas de barre oblique inverse dans votre exemple. Devrait-il ressembler à ceci: s/\#U00a9/safe/
@LeFrancisShelhamer bonne prise. Il a avalé la barre oblique inverse. Je vais modifier.
17

Pour sortir #du shell, utilisez simplement des guillemets simples ( '#'), des guillemets doubles ( "#") ou des barres obliques inverses ( \#).

Le plus simple dans votre cas serait d'utiliser la renamecommande (si elle est disponible):

rename '#U00a9' safe *.jpg
mik
la source
2
Merci. Alors que la réponse la plus votée ( rename 's/#/somethingelse/' *) ne fonctionnait pas sur ma machine (Arch Linux), celle-ci fonctionnait.
Marcvangend
1
Cela fonctionne en utilisant la commande rename de util-linux.
imclean
10

je ne sais pas comment faire, mais vous pouvez essayer ceci dans un shell bash:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

explication:

  1. parcourt tous les noms de fichiers correspondant au glob (Lucky- # U00a9NBC - *. jpg)
  2. renomme le fichier en utilisant la commande move (mv)
  3. utilise la substitution de paramètre bash native $ {var / Pattern / Replacement} pour créer le nouveau nom ("$ {f / # U00a9 / safe}")

Pour en savoir plus sur la substitution de paramètres (qui est une OMI extrêmement sous-utilisée): http://www.tldp.org/LDP/abs/html/parameter-substitution.html

Gregory Patmore
la source
Bien que ce code puisse répondre à la question, il n'est pas très utile en soi. Expliquer comment résoudre le problème améliorerait l’utilité et la valeur à long terme de la réponse.
Anthony G - justice pour Monica
ajout d'une explication pas à pas et de lectures complémentaires conformément au commentaire d'Anthony.
Gregory Patmore
1

Les exemples ci-dessus ne fonctionnaient pas sur mon système (CentOS 5.6). J'ai donc trouvé une commande (peut-être plus spécifique au système) qui fonctionne (remarque: nécessité d'échapper à '#' avec la \ligne de commande):

rename \#U00a9 safe *.jpg

[Aussi: je n'ai pas encore assez de réputation pour commenter, alors en réponse à la question de Nikhil concernant l'utilisation de /gin rename 's/old_string/new_string/g'(posée dans les commentaires pour une autre réponse ci-dessus):

Utilisez le gmodificateur pour effectuer une substitution "globale" (c'est-à-dire pour substituer new_string à old_string autant de fois que old_string se produit). Cela ne devrait pas être nécessaire dans ma réponse car le renamesera appliqué à tous les fichiers spécifiés avec *. Voir https://www.computerhope.com/unix/rename.htm pour une explication concise de ce modificateur et d'autres.]

Ezra Citron
la source
Correct; Les systèmes d'exploitation dérivés de Fedora tels que CentOS ont une version différente de renamecelle des systèmes d'exploitation dérivés de Debian. Voir unix.stackexchange.com/a/238862/135943 . Et au fait, CentOS 5.6 est assez ancien et je vous recommande de le mettre à jour.
Wildcard
Ah, merci pour l'explication + lien. Le système d'exploitation obsolète est au travail et il ne m'appartient donc pas de mettre à niveau :) mais un nouveau cluster est en construction et nous allons probablement le mettre à niveau lorsque nous passerons ...
Ezra Citron
0

Voici la solution de DTK intégrée à une fonction bash réutilisable:

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

Voici comment vous pouvez l'utiliser:

renameFilesRecursively /home/user/my-files apple orange
Slava Fomin II
la source
0

A en fait renameune option exactement pour cela appelé --substou -sen bref. Pas besoin d'utiliser la syntaxe regex.

rename -s '#U00a9' 'safe' *

Si vous souhaitez remplacer / remplacer plusieurs occurrences, utilisez --subst-allou -S.

BTW, je voulais seulement remplacer une chaîne par rien (retirez-la du nom du fichier) ... eh bien nous avons aussi une option pour elle -d/--deleteet -D/--delete-all:

rename -d '#U00a9' *
lapin
la source
-1

Une autre option consiste à utiliser pyRenamerune application spécialement conçue pour renommer des lots.

Il peut être installé avec sudo apt-get install pyrenamer

Pour plus de détails sur l'utilisation, reportez-vous à son fichier README sur GitHub .

Sajna T
la source
1
Si vous pensez vraiment que cela pourrait répondre à la question, veuillez ajouter une explication à votre réponse. De lui-même, il installe seulement un paquet. Vous devez expliquer le rôle de la commande et fournir un exemple permettant de gérer les exigences spécifiques de l'OP.
Roaima