Comment renommer par lots des fichiers dans un terminal macOS?

123

J'ai un dossier avec une série de fichiers nommés:

prefix_1234_567.png
prefix_abcd_efg.png

Je voudrais supprimer par lots un trait de soulignement et le contenu du milieu afin que la sortie soit:

prefix_567.png
prefix_efg.png

Pertinent mais pas complètement explicatif:

kidnapper
la source
Regardez la gamme et les méthodes de sous-chaîne de NSString et NSMutableString
Grady Player
1
Avez-vous envisagé des solutions non terminales à cela? Un flux de travail Automator peut effectuer ces types d'opérations avec facilité. Vous pouvez créer un flux de travail automatisé pour renommer tous les fichiers et remplacer le texte _*_par un espace.
Encryptic
Je pensais que l'automate ne pouvait pas faire de jokers
kidnim le

Réponses:

234

Dans votre cas particulier, vous pouvez utiliser la bashcommande suivante ( bashest le shell par défaut sur macOS):

for f in *.png; do echo mv "$f" "${f/_*_/_}"; done

Remarque: s'il est possible que vos noms de fichiers commencent par -, placez-les -- avant [1]:
mv -- "$f" "${f/_*_/_}"

Remarque: echoest précédé de mvpour effectuer un essai à sec. Supprimez-le pour effectuer un changement de nom réel.

Vous pouvez l'exécuter à partir de la ligne de commande ou l'utiliser dans un script.

  • "${f/_*_/_}"est une application d' bash expansion des paramètres : le (premier) modèle de correspondance de sous-chaîne _*_est remplacé par un littéral _, coupant efficacement le jeton du milieu du nom.
  • Notez qu'il _*_s'agit d'un modèle (une expression générique, comme également utilisée pour le globbing), pas une expression régulière (pour en savoir plus sur les modèles, exécuter man bashet rechercher Pattern Matching).

Si vous vous retrouvez fréquemment à renommer des fichiers par lots, envisagez d'installer un outil spécialisé tel que l' renameutilitaire basé sur Perl . Sur macOS, vous pouvez l'installer à l'aide du gestionnaire de packages populaire Homebrew comme suit:

brew install rename

Voici l'équivalent de la commande en haut utilisant rename:

rename -n -e 's/_.*_/_/'  *.png

Encore une fois, cette commande effectue un essai à vide; remove -npour effectuer un changement de nom réel.

  • Similaire à la bashsolution, s/.../.../effectue une substitution de texte, mais - contrairement à dans bash- des expressions régulières vraies sont utilisées.

[1] Le but de l'argument spécial --, qui est pris en charge par la plupart des utilitaires, est de signaler que les arguments suivants doivent être traités comme des opérandes (valeurs), même s'ils ressemblent à des options en commençant par -, comme le note Jacob C ..

mklement0
la source
3
excellente réponse, a parfaitement fonctionné. J'apprécie également que vous y soyez retourné et que vous l'ayez édité pour l'expliquer davantage et fournir une solution plus élégante si je le répète. encore une fois, merci beaucoup, très utile
kidnim le
4
Un exemple utilisant des remplacements correspondants ( .*-> $1), par exemple Renommer Foo bar S01E01 biz baz.exten S01E01.ext:rename -n -e 's/.*(S[0-9]{2}E[0-9]{2}).*(\.[a-z]{2,4})/$1$2/' *
Steve Robbins
2
J'adore l'idée d'utiliser echopour les essais à sec. Merci pour le conseil!
James Wright
Je recommande vivement de faire juste lebrew install rename
Chris Redford
98

Pour renommer des fichiers, vous pouvez utiliser l' renameutilitaire:

brew install rename

Par exemple, pour modifier une chaîne de recherche dans tous les noms de fichiers du répertoire actuel:

rename -nvs searchword replaceword *

Supprimez le paramètre «n» pour appliquer les modifications.

Plus d'informations: man rename

David Thomas
la source
1
OS Xles versions de GNU bash( x86_64-apple-darwin ) n'incluent pas l'utilitaire de changement de nom.
l'L'l
4
Merci, oui, il doit être installé viabrew install rename
David Thomas
2
Cette astuce est géniale! J'ai tapé rename -vs GLYCOPHORIN GLYCC *et maintenant il renomme automatiquement plus de 450 fichiers. Et super rapide aussi.
Sander W.van der Laan
3
Excellent! J'adore la partie "montrer ce qui serait changé" AVANT de renommer les choses!
Ben Duffin
3
Vous pouvez également utiliser une regex. renommer 's / 123 / onetwothree / g' *
Bryan
12

Vous pouvez utiliser sed:

ls * | sed -e 'p;s@_.*_@_@g' | xargs -n2 mv

résultat:

prefix_567.png prefix_efg.png

* pour effectuer d'abord un essai à sec, remplacer mvà la fin parecho

Explication:

  • e: facultatif pour 1 seule commande sed.
  • p: pour imprimer l'entrée dans sed, dans ce cas ce sera le nom du fichier d'origine avant tout changement de nom
  • @: remplace le caractère / pour rendre sed plus lisible. Autrement dit, au lieu d'utiliser sed s / search / replace / g, utilisez s @ search @ replace @ g
  • _. *: le trait de soulignement est un caractère d'échappement pour faire référence au véritable "." caractère zéro fois ou plus (par opposition à N'IMPORTE QUEL caractère dans regex)
  • -n2: indique qu'il y a 2 sorties qui doivent être transmises à mv en tant que paramètres. pour chaque entrée de ls , cette commande sed générera 2 sorties, qui seront ensuite fournies à mv.
je vais
la source
1
Solution intelligente, quoique quelque peu obscure. Rendre cela plus général, afin de prendre également en charge les noms de fichiers avec des espaces incorporés, devient encore plus obscur: ls * | xargs -I % bash -c 'echo mv "%" "$(sed 's@_.*_@_@' <<<"%")"'(supprimer echopour renommer).
mklement0
2
Ésotérique? J'aime cela!
Bilal Akil
7

J'avais un lot de fichiers qui ressemblaient à ceci: be90-01.png et j'avais besoin de changer le tiret en soulignement. J'ai utilisé ceci, qui a bien fonctionné:

for f in *; do mv "$f" "`echo $f | tr '-' '_'`"; done
JanB
la source
2

vous pouvez installer la renamecommande en utilisant brew. faites-le brew install renameet utilisez-le.

Nisim Joseph
la source
1

En utilisant mmv

mmv '*_*_*' '#1_#3' *.png
αғsнιη
la source
vous devez d'abord installer sudo apt-get install mmv.
αғsнιη
1
Étant donné qu'il s'agissait d'OS X, la procédure d'installation correcte est brew install mmv.
buckaroo1177125
1

essaye ça

for i in *.png ; do mv "$i" "${i/remove_me*.png/.png}" ; done

Voici une autre façon:

for file in Name*.png; do mv "$file" "01_$file"; done
Thiago
la source