¿Cómo puedo usar renombrar para renombrar recursivamente todo en mayúsculas?

11

Me gustaría cambiar el nombre de forma recursiva de todos los archivos y carpetas (subcarpetas) a mayúsculas.

Encontré algunos scripts que lo harán en minúsculas, pero no sé cómo cambiarlos, así que lo haré al revés (de abajo hacia arriba).

El script que encontré y funciona en minúsculas, pero no sabía cómo modificarlo es:

rename 'y/A-Z/a-z/' *

Es a partir de man rename.

jnhghy - Alexandru Jantea
fuente
Sin saber nada sobre el comando de cambio de nombre, sospecho que si lo intentas rename 'y/a-z/A-Z/' *obtendrás lo que quieres. Cuidado donde lo pruebas.
Warwick
no es recurrentemente (porque el inicial no era ...) pero funciona. No puedo entender por qué no pensé en eso :), ¡gracias!
jnhghy - Alexandru Jantea
Creo que, dada la calidad de la respuesta de Gilles, sería bueno si acepta su respuesta con preferencia a la mía. Es mucho más completo que el mío y explica sus opciones (y cómo funciona todo). Gracias.
Warwick

Respuestas:

8

Tenga en cuenta que está utilizando el script Perl llamadorename distribuido por Debian y derivados (Ubuntu, Mint, ...). Otras distribuciones de Linux incluyen un comando llamado completamente diferente y considerablemente menos útil rename.

y/A-Z/a-z/traduce cada carácter en el rango Amedio Zen el carácter correspondiente en la gama aa través z, por ejemplo, ASCII letras mayúsculas a la letra minúscula correspondiente. Para realizar la traducción opuesta, use y/a-z/A-Z/. Otra manera de escribir el mismo comando es rename '$_ = uc($_)' *uces la U pper c función del ase, y el renamecomando cambia el nombre de archivos basado en la transformación hecha a la $_variable.

rename '…' *solo cambia el nombre de los archivos en el directorio actual, porque eso es lo que *coincide. Los archivos de puntos (archivos cuyo nombre comienza con .) también se omiten.

Si desea cambiar el nombre de los archivos en el directorio actual y en subdirectorios de forma recursiva, puede utilizar el findcomando para recorrer el directorio actual de forma recursiva. Aquí hay una dificultad: si llama rename, esto cambia el nombre del directorio y la parte del nombre base. Si llama renamea un directorio antes de recurrir a él ( find -exec rename … {} \;), findse confunde porque ha encontrado un directorio pero ese directorio ya no existe cuando intenta descender a él. Puede solucionar esto diciendo findque atravesar un directorio antes de actuar sobre ella, pero luego terminan intentar cambiar el nombre foo/bara FOO/BARpero el directorio FOOno existe.

Una forma sencilla de evitar esta dificultad es hacer que el comando de cambio de nombre actúe solo en la parte del nombre base de la ruta. La expresión regular ([^/]*\Z)coincide con la parte final de la ruta que no contiene a /.

find . -depth -exec rename 's!([^/]*\Z)!uc($1)!e' {} +

El shell zsh proporciona características más convenientes para renombrar, incluso más críptico que Perl, pero más terso y, a menudo, más fácil de componer.

La función zmvrenombra archivos basados ​​en patrones. Corre autoload -U zmvuna vez para activarlo (pon esta línea en tu .zshrc).

En el primer argumento de zmv(el patrón a reemplazar), puede usar los poderosos patrones comodín de zsh . En el segundo argumento de zmv(el texto de reemplazo), puede usar sus funciones de expansión de parámetros , incluidos los modificadores del historial .

zmv -w '**/*' '$1$2:u'

Explicación:

  • -w - Asigna automáticamente variables numéricas a cada patrón comodín
  • **/*- todos los archivos en subdirectorios, recursivamente ( **/coincide con 0, 1 o más niveles de subdirectorios)
  • $1 - la primera variable numérica, que aquí coincide con la parte del directorio de cada ruta
  • $2:u- la segunda variable numérica, que aquí coincide con la parte del nombre base de cada ruta, con el :umodificador para convertir el valor a mayúsculas

Como una ventaja adicional, esto respeta la configuración regional del entorno.

Si no está seguro acerca de un zmvcomando que escribió, puede pasar la -nopción de imprimir lo que haría el comando y no cambiar nada. Verifique la salida y, si hace lo que desea, vuelva a ejecutar el comando sin -nactuar realmente.

Gilles 'SO- deja de ser malvado'
fuente
5

Robado (con una edición menor) de la publicación de Gilles aquí

find <DIR> -depth -type d -exec rename -n 's!/([^/]*/?)$!\U/$1!' {} +

Warwick
fuente
Esto no actúa de forma recursiva.
Gilles 'SO- deja de ser malvado'
Cierto. Debería haber leído la pregunta correctamente. No tengo acceso al comando de cambio de nombre, pero creo que esto va a funcionar de forma recursiva -find <dir> -exec rename 'y/a-z/A-Z/' {} \;
Warwick
Es un poco más complicado que eso, porque está cambiando el nombre de los directorios mientras findrecurre a ellos.
Gilles 'SO- deja de ser malvado'
@Gilles - OK. Después de investigar un poco, parece que necesito agregar la opción -depth para encontrar para que los nombres de directorio se manejen en último lugar. Por find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;lo tanto, debe manejar el problema de cambio de nombre de los directorios. ¿Correcto?
Warwick
No, eso todavía no funciona, porque los renamecambios , por ejemplo, foo/baren FOO/BARy FOOno existen en ese momento.
Gilles 'SO- deja de ser malvado'
2

Me gustaría dirigir a cualquiera que todavía esté vinculado a esta respuesta a la excelente respuesta que Guiles Quernot dio a esta pregunta que no requiere find.

El comando resultante sería:

shopt -s globstar
rename -n 'y/a-z/A-Z/' **

Pero antes de ejecutar, lea la respuesta vinculada a las advertencias con respecto a las versiones antiguas de bash.

Finalmente, en caso de que alguien se pregunte qué hace el y///comando perl regex. Aquí hay un enlace a la documentación relevante .

Marcelo Lacerda
fuente
1

find -execdirEl | rebautizar

Esta sería la mejor manera de hacerlo si no fuera por la locura de la ruta relativa, ya que evita que Perl regex fu solo actúe en el nombre base:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find a -depth -execdir rename 's/(.*)/\U$1/' '{}' \;

-execdirprimero cds en el directorio antes de ejecutar solo en el nombre base.

Desafortunadamente, no puedo deshacerme de esa PATHparte de piratería, se find -execdirniega a hacer nada si tiene una ruta relativa en PATH...: /ubuntu/621132/why-using-the-execdir-action- is-insecure-for-directory-which-is-in-the-path / 1109378 # 1109378

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
fuente
0

Pruebe esto después de pasar al directorio donde desea cambiar el nombre de los archivos:

for word in `ls -ltr |tail -n +2 |awk '{print $9}'`
do
  a=$(echo $word | tr '[a-z]' '[A-Z]')
  mv $word $a
  echo "Done Successfully"
done
Sorav
fuente
No analice la salida de ls (y ¿por qué demonios correría ls -lsolo para cortar las columnas que no sean el nombre?), Y use comillas dobles alrededor de sustituciones variables . Su código es demasiado complejo y se rompe en los nombres de archivo que contienen espacios en blanco y otros caracteres especiales. Use findo **/para recurrir a subdirectorios, la salida de lses solo para consumo humano.
Gilles 'SO- deja de ser malvado'