regex macos shell sed awk

Regex para lotes renombrar archivos en OS X Terminal



macos shell (5)

Mi decisión sobre un renombrador de nombres de archivos de expresiones regulares recursivo amigable que, de forma predeterminada, solo emula el reemplazo y muestra cuáles serían los nombres de los archivos resultantes.

Use -w para escribir cambios cuando esté satisfecho con el resultado de la ejecución en seco, -s para suprimir la visualización de archivos que no coinciden; -h o --help mostrará notas de uso.

El uso más simple:

# replace all occurences of ''foo'' with ''bar'' # "foo-foo.txt" >> "bar-bar.txt" ren.py . ''foo'' ''bar'' -s # only replace ''foo'' at the beginning of the filename # "foo-foo.txt" >> "bar-foo.txt" ren.py . ''^foo'' ''bar'' -s

Los grupos coincidentes (por ejemplo, /1 , /2 etc.) también son compatibles:

# rename "spam.txt" to "spam-spam-spam.py" ren.py . ''(.+)/.txt'' ''/1-/1-/1.py'' -s # rename "12-lovely-spam.txt" to "lovely-spam-12.txt" # (assuming two digits at the beginning and a 3 character extension ren.py . ''^(/d{2})-(.+)/.(.{3})'' ''/2-/1./3'' -s

NOTA: no olvide agregar -w cuando haya probado los resultados y desee escribir los cambios.

Funciona tanto con Python 2.x como con Python 3.x.

#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import print_function import argparse import os import fnmatch import sys import shutil import re def rename_files(args): pattern_old = re.compile(args.search_for) for path, dirs, files in os.walk(os.path.abspath(args.root_folder)): for filename in fnmatch.filter(files, "*.*"): if pattern_old.findall(filename): new_name = pattern_old.sub(args.replace_with, filename) filepath_old = os.path.join(path, filename) filepath_new = os.path.join(path, new_name) if not new_name: print(''Replacement regex {} returns empty value! Skipping''.format(args.replace_with)) continue print(new_name) if args.write_changes: shutil.move(filepath_old, filepath_new) else: if not args.suppress_non_matching: print(''Name [{}] does not match search regex [{}]''.format(filename, args.search_for)) if __name__ == ''__main__'': parser = argparse.ArgumentParser(description=''Recursive file name renaming with regex support'') parser.add_argument(''root_folder'', help=''Top folder for the replacement operation'', nargs=''?'', action=''store'', default=''.'') parser.add_argument(''search_for'', help=''string to search for'', action=''store'') parser.add_argument(''replace_with'', help=''string to replace with'', action=''store'') parser.add_argument(''-w'', ''--write-changes'', action=''store_true'', help=''Write changes to files (otherwise just simulate the operation)'', default=False) parser.add_argument(''-s'', ''--suppress-non-matching'', action=''store_true'', help=''Hide files that do not match'', default=False) args = parser.parse_args(sys.argv[1:]) print(args) rename_files(args)

Estoy buscando una manera de cambiar el nombre de los archivos con una expresión regular por ej.

s/123/onetwothree/g

Recuerdo que puedo usar awk y sed con una expresión regular, pero no pude averiguar cómo unirlos para obtener el resultado deseado.


Namechanger es super agradable. Es compatible con expresiones regulares para buscar y reemplazar:


Puede instalar la utilidad de cambio de nombre basado en Perl:

brew install rename

y que simplemente usarlo como:

rename ''s/123/onetwothree/g'' *

Si desea probar su expresión regular sin cambiar el nombre de ningún archivo, simplemente agregue el interruptor -n


Una forma eficiente de realizar la operación de cambio de nombre es construir los comandos de cambio de nombre en una tubería sed y enviarlos al shell.

ls | sed -n ''s//(.*/)/(123/)/(.*/)/mv "/1/2/3" "/1onetwothree/2"/p'' | sh


files = "*" for f in $files; do newname=`echo "$f" | sed ''s/123/onetwothree/g''` mv "$f" "$newname" done