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.
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