¿Hay un comando de Linux como mv pero con regex?

Respuestas:

32

Como otros han mencionado, renamees bueno en esto, pero lea la página de manual ( man rename) antes de intentarlo. Hay al menos dos herramientas completamente diferentes que se llaman renamey cuál tendrá dependerá de su distribución. Llamarlos incorrectamente puede ser peligroso.

Aquí está la página del manual para la versión basada en Perl de Larry Wall que se incluye con Ubuntu. Le das una expresión perl comorename 's/\.sql$/.php/' *.sql

Aquí está la página del manual para el cambio de nombre que se distribuye con distribuciones anteriores de Red Hat y CentOS. El uso es una simple sustitución de cadena comorename .sql .php *.sql

También puede usar un bash one-liner para procesar cada archivo de uno en uno:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Ryan Bright
fuente
¿Alguien podría cargar un binario de Windows para el cambio de nombre basado en Perl?
mcandre
El cambio de nombre de la versión Perl no puede mover archivos de un sistema de archivos a otro.
lilydjwg
bash one-liner es útil, especialmente cuando no tiene renamefunción (es decir, busybox)
artm
10

Hay rename(1), que no usa expresiones regulares, pero puede resolver su problema:

rename .sql .php *.sql

También hay mmv(1), pero no estoy familiarizado con cómo funciona.

Adam Rosenfield
fuente
En Ubuntu y Debian (no estoy seguro acerca de otras distribuciones), /usr/bin/renameenlaces a /usr/bin/prenamepor defecto, que toma expresiones regulares.
phaphink
5

G'day

También podrías intentar ingresar

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

O para hacerlo usar regex's cámbialo ligeramente a

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

para un poco de diversión de codificación de shell. (-:

Rob Wells
fuente
2
Esto falla con los archivos que contienen espacios en blanco en su nombre, así que tenga cuidado. Uno nuncals debe analizar la salida .
slhck
Sin sedembargo, el ejemplo es bastante bueno.
estrella brillante
2

Siendo fontanero, me gustan las pipas :)

Nota: esta respuesta es detallada: como nuevo aprendiz, agradezco que alguien que sabe se tome el tiempo de explicar, así que estoy pagando 'adelante'. Si no eres un novato, disculpa la longitud y la verbosidad.

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

Dónde:

ls -1 *_201[67][0-9]*

enumera todos los archivos que coinciden con el patrón, en este caso estoy buscando archivos con la fecha en el nombre del archivo en el formulario 'AAAAMMDD'

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1: primer grupo de captura: el nombre de archivo completo

^ 2: 2do grupo de captura - la 1ra parte del patrón de nombre de archivo

^ 3: 3er grupo de captura - la 2da parte del nombre de archivo - aquí, la fecha como 'AAAAMMDD'

^ 4: 4to grupo de captura: parte opcional del nombre de archivo entre la fecha y la extensión, y la extensión misma

Sooooo .... si tengo un archivo llamado

CallLog_555123412_20161231-214403.7z

...luego

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

en realidad significa

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

Tenga en cuenta que la salida del comando sed se canaliza a 'bash' para ejecutarlo. Para ver primero los movimientos del archivo propuesto SIN moverlos realmente, primero quite el '| bash 'al final, e inténtalo así:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

Esto no hará ningún cambio en absoluto, pero verá el comando que se ejecutará SI lo ejecuta con '| bash 'etiquetado en el final.

Esto es útil porque puede crear cualquier subdirectorio que desee a partir de partes en el nombre del archivo, o cualquier otra cosa que agregue al texto de 'reemplazo' en el comando sed. Sin embargo, tenga en cuenta que sed requiere muchos caracteres de escape.

Soportes SED Regex:

(...) requieren escapar para la agrupación de captura -> \ (... \)

{m, n} requiere escapar para cuantificar el objeto anterior -> \ {m, n \}

/ requiere escapar en la cadena de reemplazo -> \ /

[...] NO requieren escapar para las clases de personajes

\ 1 en la cadena de reemplazo se refiere al primer grupo capturado, y así sucesivamente ...

ADVERTENCIA DE SEGURIDAD: NUNCA TUBE NADA PARA 'golpear' A MENOS QUE COMPRENDA TOTALMENTE EL RESULTADO ...

Espero que ayude a eliminar algunos bloqueos :)

skeetastax
fuente
1

Instalar mmv, luego haz esto:

mmv "*.sql" "#1.php"
Gepsens
fuente