¿Cómo cambio la extensión de varios archivos?

168

Me gustaría cambiar una extensión de archivo de *.txta *.text. Intenté usar el basenamecomando, pero tengo problemas para cambiar más de un archivo.

Aquí está mi código:

files=`ls -1 *.txt`

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

Recibo este error:

basename: too many arguments Try basename --help' for more information
afbr1201
fuente
Algunas ideas en peteryu.ca/tutorials/shellscripting/batch_rename también
Nemo

Respuestas:

176

Directamente de Greg's Wiki :

# Renombrar todo * .txt a * .text
para f en * .txt; hacer
    mv - "$ f" "$ {f% .txt} .text"
hecho

También vea la entrada sobre por qué no debe analizarls .

Editar: si tiene que usar basenamesu sintaxis sería:

para f en * .txt; hacer
    mv - "$ f" "$ (nombre base -" $ f ".txt) .text"
hecho
jasonwryan
fuente
48
Hay una sintaxis de Bash ligeramente avanzada utilizada aquí sin explicación. Tuve que buscar en Google muchas cosas para entender esto completamente. Para ayudar a otros en mi posición, aquí hay algunas referencias sobre globs (la *.txtsintaxis) , el doble guión simple-- y el uso del símbolo% dentro de la ${}construcción . Hasta ahora nunca me había encontrado con los dos últimos y no sabía lo que realmente estaba sucediendo con el primero.
Mark Amery
3
Mire la respuesta de Matthias Braun a continuación: mucho más simple, logra lo mismo.
btk
10
One linerfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan
1
Tienes una falta; después del texto ".
Pétur Ingi Egilsson
2
@ PéturIngiEgilsson en la segunda línea? No, no es obligatorio
jasonwryan
132

Así es como cambio todas las extensiones de archivo en el directorio actual en Debian.

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

(Este es el renamecomando Perl , no el util-linuxindicado. Vea ¿Por qué la utilidad de cambio de nombre en Debian / Ubuntu es diferente a la de otras distribuciones, como CentOS? )

Matthias Braun
fuente
10
Mucho más simple que la respuesta aceptada, ¡gracias!
btk
8
En Mac pude brew install renamey conseguí que esto funcionara.
Monkpit
3
con concha de pescado que puede hacer rename "s/oldExtension/newExtension/" **.txtpara cambiar el nombre de todos * .txt recursivamente
Palmstrom
3
Esto fallará por footxt.txt. Utilice esto en su lugar: unix.stackexchange.com/questions/19654/…
wisbucky
77
Cuando sus archivos no tienen ninguna extensión y desea agregar una:rename 's/$/.txt/' *
mkataja
35

Un comando simple, renamefromutil-linux , lo hará por usted, reemplazará todas las apariciones de "txt" a "texto" en todos los archivos que coincidan con "* .txt":

rename txt text *.txt
lamwaiman1988
fuente
44
renamecambia la primera aparición, por lo que es mejor hacerlo rename .txt .text, pero esto no siempre funcionará (por ejemplo, cambia el nombre foo.txtx.bar.txta foo.textx.bar.txt).
Gilles
12
Cabe señalar que no todos los sistemas tienen la misma versión de cambio de nombre; en Debian y sus amigos, el renamecomando es en realidad perl-renamey usa expresiones regulares perl. Por eso, el comando equivalente sería: rename 's/.txt/.text/' *.txt. Las personas deben verificar man renameen su sistema para averiguar cuál tienen.
evilsoup
@evilsoup Ese es el caso de OSX, thx
Davi Lima
Esto también funciona en Cygwin (Windows)
Andy
27
rename "s/oldExtension/newExtension/" *.txt

Lo anterior funciona bien pero limitado al directorio actual. Pruebe el siguiente comando, que es flexible con subdirectorios. Cambiará el nombre de todos los .txtarchivos en la estructura de directorios con una nueva extensión.

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;
Rahul
fuente
2
renamepuede manejar múltiples archivos como argumento, puede acelerar enormemente las cosas usando en +lugar de \;si hay muchos de esos archivos
Anthon
Aún así, es una opción útil ya que "* .txt" puede desplegarse en una lista de argumentos grande que no es compatible con el shell.
Roman Shapovalov
1
"s / oldExtension / newExtension /" fallará por footxt.txt. Utilice esto en su lugar: unix.stackexchange.com/questions/19654/…
wisbucky
9
for f in *.txt
do
    [ -f "$f" ] && mv "$f" "${f%txt}text"
done
Príncipe John Wesley
fuente
9

Las respuestas aquí haciendo referencia s/oldExtension/newExtension/son incorrectas. Si lo usa s/txt/text/, se convertiría footxt.txta footext.txt, que no es lo que desea. Incluso si usa s/.txt/.text/, eso se convertiría footxt.txta fo.text.txt.

Tienes que usar \.para que coincida con el período ( .coincidirá con cualquier personaje). Y el final $para que coincida con el final de la línea. Solo esto coincidirá adecuadamente con la extensión.

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

rename 's/\.old$/.new/' *.old
Wisbucky
fuente
7

Basado en la respuesta de @Prince John Wesley, aquí hay un script bash simple para cambiar todas las extensiones de archivos en el directorio actual de ext1a ext2. También genera nombres de los archivos que se renombran.

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

Ejemplo de uso (suponiendo que el nombre del script es change-ext):

change-ext ext1 ext2
Dennis Golomazov
fuente
Para cambiar extensiones de archivos en directorios de forma recursiva, reemplace la segunda línea ( for...) con dos líneas: shopt -s globstary for f in **/*.$1. Requiere Bash 4+.
Dennis Golomazov
4

Motivo # 53 para cambiar a zsh:

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

Benitok
fuente
3

supongamos que sus archivos están dispersos en varios directorios, suponiendo que dirx sea su directorio principal, esto puede hacer el trabajo usando find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done
Arash
fuente
¿Qué pasa con tcsh ..
Josef Klimuk
2

Esto es lo que funciona para mí:

find . -name '*.txt' -exec rename 's/\.txt$/.text/' \{} \;
yegor256
fuente
1
POR FAVOR agregue a. antes del "texto"
danielmhanover
2

Cuando tú

no tiene una extensión para los archivos de origen

y la extensión de destino es .text lo haría de esta manera:

for f in *; do mv -- "$f" "${f%.\*}.text"; done
nitinr708
fuente
1
Excelente script nativo de bash. funcionó genial! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce
1

En caso de que desee saber qué salió mal en su versión: utilizó en $fileslugar del $xcomando basename. Por lo tanto, esto debería funcionar (sin probar):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
daniel kullmann
fuente