Respuestas:
Para una mejor solución (con solo la funcionalidad bash, a diferencia de las llamadas externas), consulte una de las otras respuestas .
Lo siguiente haría y no requiere que el sistema tenga el rename
programa (aunque lo más frecuente es que tenga esto en un sistema):
for file in *.html; do
mv "$file" "$(basename "$file" .html).txt"
done
EDITAR: como se señaló en los comentarios, esto no funciona para los nombres de archivo con espacios en ellos sin una cita adecuada (ahora se agregó anteriormente). Cuando trabaje solo en sus propios archivos que sabe que no tienen espacios en los nombres de archivos, esto funcionará, pero siempre que escriba algo que pueda reutilizarse más adelante, no omita las citas adecuadas.
ren *.a *.b
$()
sintaxis de retroceso heredada especificada por POSIX en lugar de. Mejora la legibilidad y hace que la sintaxis sea mucho menos ambigua cuando tienes caracteres que necesitarían una barra invertida para que sea literal dentro de la sustitución de comandos con este último.
Si usa bash, no hay necesidad de comandos externos como sed, basename, rename, expr, etc.
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
"${file%.*}.txt"
, pero esto podría ser peligroso para los archivos sin extensión.
$
dentro de las llaves!
--
"operador": mv - "$ file" "$ {file% .html} .txt" Ese operador evita los nombres de archivos que comienzan con un '-' de ser analizado por mv como argumentos.
rename 's/\.html$/\.txt/' *.html
hace exactamente lo que quieres
Esto funcionó para mí en OSX de .txt a .txt_bak
find . -name '*.txt' -exec sh -c 'mv "$0" "${0%.txt}.txt_bak"' {} \;
.txt
a .txt_bak
sólo hay que concatenar _bak
;)
.scss
a .sass
(después de la conversión en el lugar ...):find . -name '*.scss' -exec sh -c 'mv "$0" "${0%.scss}.sass"' {} \;
Quieres usar rename
:
rename -S .html .txt *.html
Esto hace exactamente lo que desea: cambiará la extensión de .html
a .txt
para todos los archivos que coincidan *.html
.
Nota: Greg Hewgill señala correctamente que esto no es un bash incorporado; y es un comando separado de Linux. Si solo necesita algo en Linux, esto debería funcionar bien; Si necesita algo más multiplataforma, eche un vistazo a una de las otras respuestas.
rename
programa no está relacionado bash
y tampoco está disponible en todas las plataformas. Solo lo he visto en Linux.
rename -S .html .text *.html
que -S
representa--subst-all
Para usuarios de Ubuntu:
rename 's/\.html$/\.txt/' *.html
Aquí hay un ejemplo del comando renombrar:
rename -n ’s/\.htm$/\.html/’ *.htm
El -n significa que es una prueba de funcionamiento y que en realidad no cambiará ningún archivo. Le mostrará una lista de archivos que cambiarían de nombre si eliminara -n. En el caso anterior, convertirá todos los archivos en el directorio actual de una extensión de archivo de .htm a .html.
Si el resultado de la ejecución de prueba anterior se veía bien, entonces podría ejecutar la versión final:
rename -v ’s/\.htm$/\.html/’ *.htm
El -v es opcional, pero es una buena idea incluirlo porque es el único registro que tendrá de los cambios que realizó el comando renombrar como se muestra en la salida de muestra a continuación:
$ rename -v 's/\.htm$/\.html/' *.htm
3.htm renamed as 3.html
4.htm renamed as 4.html
5.htm renamed as 5.html
La parte difícil en el medio es una sustitución de Perl con expresiones regulares, resaltada a continuación:
rename -v ’s/\.htm$/\.html/’ *.htm
Esta pregunta menciona explícitamente a Bash, pero si tiene ZSH disponible, es bastante simple:
zmv '(*).*' '$1.txt'
Si obtienes zsh: command not found: zmv
, simplemente ejecuta:
autoload -U zmv
Y luego inténtalo de nuevo.
Gracias a este artículo original por el consejo sobre zmv.
Después del rastreo del sitio web de otra persona, terminé con miles de archivos sin la extensión .html, en un amplio árbol de subdirectorios.
Para cambiarles el nombre a todos de una vez, excepto los archivos que ya tienen una extensión .html (la mayoría de ellos no tenían ninguno), esto funcionó para mí:
cd wwwroot
find . -xtype f \! -iname *.html -exec mv -iv "{}" "{}.html" \; # batch rename files to append .html suffix IF MISSING
En el caso del OP, podría modificarlo ligeramente, solo para cambiar el nombre de los archivos * .txt, de esta manera:
find . -xtype f -iname *.txt -exec filename="{}" mv -iv ${filename%.*}.{txt,html} \;
Desglosado (hammertime!):
-iname * .txt
: significa considerar SOLAMENTE los archivos que ya terminan en .txt
mv -iv "{}. {txt, html}" - Cuando find pasa a {} como nombre de archivo, $ {filename%. *} extrae su nombre base sin ninguna extensión para formar los parámetros a mv . bash toma el {txt, html} para reescribirlo como dos parámetros para que el comando final se ejecute como:mv -iv "filename.txt" "filename.html"
Corrección necesaria: tratar con espacios en los nombres de archivo
El comandommv
parece realizar esta tarea de manera muy eficiente en una gran cantidad de archivos (decenas de miles en un segundo). Por ejemplo, para cambiar el nombre de todos los .xml
archivos a .html
archivos, use esto:
mmv ";*.xml" "#1#2.html"
la ;
coincidirá con la trayectoria, la *
coincidirá con el nombre del archivo, y éstos se conocen como #1
y #2
en el nombre de reemplazo.
Las respuestas basadas en exec
o tuberías fueron demasiado lentas o fallaron en una gran cantidad de archivos.
Prueba esto
rename .html .txt *.html
uso:
rename [find] [replace_with] [criteria]
Un poco tarde para la fiesta. Podrías hacerlo con xargs:
ls *.html | xargs -I {} sh -c 'mv $1 `basename $1 .html`.txt' - {}
O si todos tus archivos están en alguna carpeta
ls folder/*.html | xargs -I {} sh -c 'mv $1 folder/`basename $1 .html`.txt' - {}
ls
. Este comando es ridículo: inútilmente usa un glob con ls
, en lugar de usar directamente el glob. Esto se romperá con nombres de archivo que contengan espacios, comillas y (debido a la falta de comillas) caracteres globales.
Esta es una buena manera de modificar múltiples extensiones a la vez:
for fname in *.{mp4,avi}
do
mv -v "$fname" "${fname%.???}.mkv"
done
Nota: tenga cuidado en que el tamaño de la extensión sea el mismo (el ???)
Si prefiere PERL, hay un breve script PERL (originalmente escrito por Larry Wall, el creador de PERL) que hará exactamente lo que quiere aquí: tips.webdesign10.com/files/rename.pl.txt .
Para su ejemplo, lo siguiente debería hacer el truco:
rename.pl 's/html/txt/' *.html
De manera similar a lo que se sugirió antes, así es como lo hice:
find . -name '*OldText*' -exec sh -c 'mv "$0" "${0/OldText/NewText}"' {} \;
Primero validado con
find . -name '*OldText*' -exec sh -c 'echo mv "$0" "${0/OldText/NewText}"' {} \;
Una línea, sin bucles:
ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
Ejemplo:
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.json ac8453e2-0d82-4d43-b80e-205edb754700.json
$ ls -1 | xargs -L 1 -I {} bash -c 'mv $1 "${1%.*}.txt"' _ {}
$ ls
60acbc4d-3a75-4090-85ad-b7d027df8145.txt ac8453e2-0d82-4d43-b80e-205edb754700.txt
Lamentablemente, no es trivial hacerlo de forma portátil. Probablemente necesites un poco de magia expr.
for file in *.html; do echo mv -- "$file" "$(expr "$file" : '\(.*\)\.html').txt"; done
Elimina el eco una vez que estés feliz de que haga lo que quieras.
Editar: basename
es probablemente un poco más legible para este caso en particular, aunque expr
es más flexible en general.
Esto es lo que solía cambiar el nombre de los .edge
archivos a.blade.php
for file in *.edge; do mv "$file" "$(basename "$file" .edge).blade.php"; done
Funciona como encanto.
También puede hacer una función en Bash, agregarla .bashrc
o algo y luego usarla donde desee.
change-ext() {
for file in *.$1; do mv "$file" "$(basename "$file" .$1).$2"; done
}
Uso:
change-ext css scss
Fuente del código en función: https://stackoverflow.com/a/1224786/6732111
Cambie el nombre de las extensiones de archivo para todos los archivos en el directorio actual y subdirectorios sin ningún otro paquete (solo use script de shell):
Cree un script de shell rename.sh
en el directorio actual con el siguiente código:
#!/bin/bash
for file in $(find . -name "*$1"); do
mv "$file" "${file%$1}$2"
done
Ejecútalo por ./rename.sh .old .new
.
P.ej. ./rename.sh .html .txt