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
afbr1201
la source
Quelques idées sur peteryu.ca/tutorials/shellscripting/batch_rename aussi
Nemo

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é
jasonwryan
la source
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? )

Matthias Braun
la source
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
lamwaiman1988
la source
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/' {} \;
Rahul
la source
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
for f in *.txt
do
    [ -f "$f" ] && mv "$f" "${f%txt}text"
done
Prince John Wesley
la source
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
sage
la source
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
Dennis Golomazov
la source
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'

Benitok
la source
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
Arash
la source
Qu'en est-il de tcsh ..
Josef Klimuk
2

C'est ce qui fonctionne pour moi:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;
yegor256
la source
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
nitinr708
la source
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
daniel kullmann
la source