bash - nombre - Utilizando sed a masa renombrar archivos
renombrar varios archivos con mv (10)
Objetivo
Cambia estos nombres de archivo:
- F00001-0708-RG-biasliuyda
- F00001-0708-CS-akgdlaul
- F00001-0708-VF-hioulgigl
a estos nombres de archivo:
- F0001-0708-RG-biasliuyda
- F0001-0708-CS-akgdlaul
- F0001-0708-VF-hioulgigl
Código de Shell
Probar:
ls F00001-0708-*|sed ''s//(./)./(.*/)/mv & /1/2/''
Actuar:
ls F00001-0708-*|sed ''s//(./)./(.*/)/mv & /1/2/'' | sh
Mi pregunta
No entiendo el código sed. Entiendo lo que el comando de sustitución
$ sed ''s/something/mv''
medio. Y entiendo algo de expresiones regulares. Pero no entiendo lo que está sucediendo aquí:
/(./)./(.*/)
o aquí:
& /1/2/
El primero, para mí, simplemente parece que significa: "un solo personaje, seguido de un solo personaje, seguido de cualquier secuencia de longitud de un solo personaje", pero seguramente hay más que eso. En cuanto a la última parte:
& /1/2/
No tengo idea. Realmente quiero entender este código. Por favor, ayúdenme, muchachos.
El comando sed
s//(./)./(.*/)/mv & /1/2/
significa reemplazar:
/(./)./(.*/)
con:
mv & /1/2
al igual que un comando sed
regular. Sin embargo, los paréntesis, &
y /n
marcadores lo cambian un poco.
La cadena de búsqueda coincide (y recuerda como patrón 1) con el carácter individual al comienzo, seguido de un carácter único, seguido del resto de la cadena (recordada como patrón 2).
En la cadena de reemplazo, puede consultar estos patrones combinados para usarlos como parte del reemplazo. También puede referirse a la parte completa coincidente como &
.
Entonces, lo que ese comando sed
está haciendo es crear un comando mv
basado en el archivo original (para la fuente) y el carácter 1 y 3 en adelante, eliminando efectivamente el carácter 2 (para el destino). Le dará una serie de líneas a lo largo del siguiente formato:
mv F00001-0708-RG-biasliuyda F0001-0708-RG-biasliuyda
mv abcdef acdef
y así.
En primer lugar, debería decir que la forma más fácil de hacerlo es usar los comandos prename o rename.
En Ubuntu, OSX ( rename
paquete Homebrew, paquete de MacPorts p5-file-rename
) u otros sistemas con perl rename (prename):
rename s/0000/000/ F0000*
o en sistemas con cambio de nombre de util-linux-ng, como RHEL:
rename 0000 000 F0000*
Eso es mucho más comprensible que el comando sed equivalente.
Pero en cuanto a la comprensión del comando sed, la página de manual de sed es útil. Si ejecuta man sed y busca & (usando el comando / para buscar), encontrará que es un carácter especial en s / foo / bar / replacements.
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successâ
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes /1 through /9 to refer to the corresponding matching
sub-expressions in the regexp.
Por lo tanto, /(./)
Coincide con el primer carácter, al cual se puede hacer referencia mediante /1
. Entonces .
coincide con el siguiente carácter, que siempre es 0. Entonces /(.*/)
coincide con el resto del nombre del archivo, al cual se puede hacer referencia mediante /2
.
La cadena de reemplazo lo ensambla todo usando &
(el nombre de archivo original) y /1/2
que es cada parte del nombre de archivo excepto el 2 ° carácter, que era un 0.
Esta es una forma bastante críptica de hacer esto, en mi humilde opinión. Si por alguna razón el comando rename no estuviera disponible y quisieras usar sed para hacer el cambio de nombre (¿o quizás estabas haciendo algo demasiado complejo para renombrar?), Ser más explícito en tu expresión regular lo haría mucho más legible. Quizás algo como:
ls F00001-0708-*|sed ''s/F0000/(.*/)/mv & F000/1/'' | sh
Poder ver lo que realmente está cambiando en s / search / replacement / lo hace mucho más legible. Tampoco seguirá chupando caracteres de tu nombre de archivo si accidentalmente lo ejecutas dos veces o algo así.
Escribí una pequeña publicación con ejemplos sobre el cambio de nombre de lotes usando sed
par de años:
http://www.guyrutenberg.com/2009/01/12/batch-renaming-using-sed/
Por ejemplo:
for i in *; do
mv "$i" "`echo $i | sed "s/regex/replace_text/"`";
done
Si la expresión regular contiene grupos (por ejemplo, /(subregex/
), puede usarlos en el texto de reemplazo como /1/
, /2
etc.
Esto es lo que haría:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi /"$file/" `jhead $file|
grep Date|
cut -b 16-|
sed -e ''s/:/-/g'' -e ''s/ /_/g'' -e ''s/$/.jpg/g''` ;
done
Entonces, si se ve bien, agregue | sh
| sh
hasta el final Asi que:
for file in *.[Jj][Pp][Gg] ;do
echo mv -vi /"$file/" `jhead $file|
grep Date|
cut -b 16-|
sed -e ''s/:/-/g'' -e ''s/ /_/g'' -e ''s/$/.jpg/g''` ;
done | sh
La forma más fácil sería:
for i in F00001*; do mv "$i" "${i/F00001/F0001}"; done
o, portably,
for i in F00001*; do mv "$i" "F0001${i#F00001}"; done
Esto reemplaza el prefijo F00001
en los nombres de archivo con F0001
. créditos a mahesh aquí: http://www.debian-administration.org/articles/150
La técnica de barra invertida-paren significa, "mientras coincides con el patrón, agárrate a las cosas que coincidan aquí". Más tarde, en el lado del texto de reemplazo, puede recuperar los fragmentos recordados con "/ 1" (primer bloque entre paréntesis), "/ 2" (segundo bloque), y así sucesivamente.
Los paréntesis capturan cadenas específicas para el uso de los números de barra invertida.
Si todo lo que estás haciendo realmente es eliminar el segundo personaje, independientemente de lo que sea, puedes hacer esto:
s/.//2
pero tu comando es construir un comando mv
y conectarlo al shell para su ejecución.
Esto no es más legible que tu versión:
find -type f | sed -n ''h;s/.//4;x;s/^/mv /;G;s//n/ /g;p'' | sh
El cuarto carácter se elimina porque find
está anteponiendo cada nombre de archivo con "./".
tuviste tu explicación sed, ahora puedes usar solo el caparazón, no necesitas comandos externos
for file in F0000*
do
echo mv "$file" "${file/#F0000/F000}"
# ${file/#F0000/F000} means replace the pattern that starts at beginning of string
done
ls F00001-0708-*|sed ''s|^F0000/(.*/)|mv & F000/1|'' | bash