Comment changer l'extension de plusieurs fichiers?


168

Je voudrais changer une extension de fichier de *.txtà *.text. J'ai essayé d'utiliser la basenamecommande, mais je ne parviens pas à modifier plusieurs fichiers.

Voici mon code:

files=`ls -1 *.txt`

for x in $files
do
    mv $x "`basename $files .txt`.text"
done

Je reçois cette erreur:

basename: too many arguments Try basename --help' for more information

Réponses:


176

Tout droit du wiki de Greg :

# Renomme tout * .txt en * .text
pour f dans * .txt; faire
    mv - "$ f" "$ {f% .txt} .text"
terminé

Voir également l'entrée sur pourquoi vous ne devriez pas analyserls .

Edit: si vous devez utiliser basenamevotre syntaxe serait:

pour f dans * .txt; faire
    mv - "$ f" "$ (nom de base -" $ f ".txt) .text"
terminé

48
Il y a une syntaxe Bash légèrement avancée utilisée ici sans explication. Il me fallait beaucoup de choses sur Google pour comprendre cela pleinement. Pour aider les autres dans ma position, voici quelques références concernant les globs (la *.txtsyntaxe) , le double tiret nu-- et l'utilisation du symbole% dans la ${}construction . Jusqu'à présent, je n'avais jamais rencontré les deux derniers et je ne savais pas ce qui se passait réellement avec les premiers.
Mark Amery

3
Regardez la réponse de Matthias Braun ci-dessous - beaucoup plus simple, accomplit la même chose.
btk

10
Un paquebotfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan

1
Vous avez un manquant; after text ".
Pétur Ingi Egilsson le

2
@ PéturIngiEgilsson en deuxième ligne? Non, ce n'est pas obligatoire.
jasonwryan

133

Voici comment je modifie toutes les extensions de fichiers du répertoire actuel de Debian.

rename "s/oldExtension/newExtension/" *.txt

(Il s'agit de la renamecommande Perl , pas de celle- util-linuxci. Voir Pourquoi l'utilitaire de changement de nom sur Debian / Ubuntu est-il différent de celui utilisé sur d'autres distributions, comme CentOS? )


10
Beaucoup plus simple que la réponse acceptée, merci!
btk

8
Sur Mac, j'ai pu brew install renameet faire en sorte que cela fonctionne.
Monkpit

3
avec une coquille de poisson, vous pouvez faire rename "s/oldExtension/newExtension/" **.txtpour renommer tous les fichiers * .txt de manière récursive
Palmstrom

3
Cela va échouer pour footxt.txt. Utilisez plutôt ceci: unix.stackexchange.com/questions/19654/…
wisbucky

7
Lorsque vos fichiers n'ont aucune extension et que vous souhaitez en ajouter une:rename 's/$/.txt/' *
mkataja

35

Une commande simple, le à renamepartirutil-linux , le fera pour vous, il remplace toutes les occurences de « txt » à « texte » dans toute correspondance de fichier « * .txt »:

rename txt text *.txt

4
renamechange la première occurrence, afin de mieux faire que rename .txt .text, mais cela ne fonctionne toujours pas toujours (par exemple , il renomme foo.txtx.bar.txtà foo.textx.bar.txt).
Gilles

12
Il convient de noter que tous les systèmes n’ont pas la même version de rename; sur Debian et ses amis, la renamecommande est en fait perl-renameet utilise des expressions rationnelles perl. Pour cela, la commande équivalente serait: rename 's/.txt/.text/' *.txt. Les gens devraient vérifier man renameleur système pour savoir lequel ils ont.
Evilsoup

@evilsoup C'est le cas pour OSX, thx
Davi Lima

Cela fonctionne également sur Cygwin (Windows)
andy

27
rename "s/oldExtension/newExtension/" *.txt

Ci-dessus fonctionne bien mais limité au répertoire en cours. Essayez la commande ci-dessous, qui est flexible avec les sous-répertoires. Il renommera tous les .txtfichiers sous la structure de répertoires avec une nouvelle extension.

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;

2
renamepeut gérer plusieurs fichiers en argument, vous pouvez considérablement accélérer les choses en utilisant à la +place de \;s'il existe beaucoup de fichiers de ce type
Anthon

Néanmoins, c’est une option utile, car "* .txt" peut se dérouler dans une liste d’arguments volumineuse non prise en charge par le shell.
Roman Shapovalov

1
"s / oldExtension / newExtension /" échouera pour footxt.txt. Utilisez plutôt ceci: unix.stackexchange.com/questions/19654/…
wisbucky


9

Les réponses ici référencées s/oldExtension/newExtension/sont fausses. Si vous utilisez s/txt/text/, vous convertiriez footxt.txten footext.txt, ce qui n'est pas ce que vous voulez. Même si vous utilisez s/.txt/.text/, cela se convertirait footxt.txten fo.text.txt.

Vous devez utiliser \.pour faire correspondre la période ( .correspond à n'importe quel caractère). Et la fuite $pour correspondre à la fin de la ligne. Seulement cela correspondra correctement à l'extension.

rename 's/\.txt$/.text/' *.txt

rename 's/\.old$/.new/' *.old

7

Sur la base de la réponse Wesley @Prince John, voici un simple script bash pour changer toutes les extensions de fichiers dans le répertoire courant de ext1la ext2. Affiche également les noms des fichiers en cours de changement de nom.

#!/bin/bash
for f in *.$1
do
    [ -f "$f" ] && mv -v "$f" "${f%$1}$2"
done

Exemple d'utilisation (en supposant que le nom du script soit change-ext):

change-ext ext1 ext2

Pour changer les extensions de fichiers dans les répertoires de manière récursive, remplacez la deuxième ligne ( for...) par deux lignes: shopt -s globstaret for f in **/*.$1. Nécessite Bash 4+.
Dennis Golomazov

4

Raison n ° 53 pour passer à zsh:

zmv '(*).txt' '$1.text'


3

Supposons que vos fichiers sont dispersés dans différents répertoires. En supposant que dirx soit votre répertoire parent, vous pouvez effectuer le travail à l'aide de find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done

Qu'en est-il de tcsh ..
Josef Klimuk

2

C'est ce qui fonctionne pour moi:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;

1
S'IL VOUS PLAÎT ajouter un. avant le "texte"
danielmhanover

2

Lorsque vous

ne pas avoir une extension pour les fichiers source

et l'extension cible est .text vous le feriez de cette façon -

for f in *; do mv -- "$f" "${f%.\*}.text"; done

1
Excellent script bash-natif. a bien fonctionné! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce le

1

Si vous voulez savoir ce qui ne va pas dans votre version: Vous avez utilisé à la $filesplace de $xla commande basename. Donc, cela devrait fonctionner (non testé, cependant):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.