Quiero cambiar todos los nombres de archivos, ya que tienen la longitud exacta de 16 caracteres (dígitos y letras minúsculas). Probé [0-9a-z]{16}
y [0-9a-z]\{16\}
para el marcador de posición regX
en el siguiente fragmento, pero no funciona.
for file in <regX>
do
mv "$file" "${file}.txt"
done
Respuesta1
Patrones globulares de conchasno son expresiones regulares. Pueden parecer similares, pero funcionan de manera bastante diferente en algunos aspectos.
La expresión regular [0-9a-z]{16}
coincide con una cadena que contiene una serie de 16 caracteres del rango de caracteres mencionado (la cadena que contiene la coincidencia puede ser más larga).
El patrón de globo de caparazón equivalente sería algo así como
*[0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]*
Esto es porque
- Los patrones globales no admiten modificadores que digan "repetir las N veces anteriores".
- Los patrones globales están anclados de forma predeterminada al principio y al final. Por eso lo inserté
*
al principio y al final del patrón. A*
coincide con cualquier número de cualquier carácter. Elimínalos si quieres que coincidanexactamente16 caracteres.
Puedes crear una cadena de 16 [0-9a-z]
usando Perl:
$ pattern="$( perl -e 'print "[0-9a-z]" x 16' )"
Con bash
, puede optar por iterar sobre todos los nombres en el directorio actual y luego probar si los nombres coinciden con su expresión regular:
for name in *; do
if [[ -f "$name" ]] && [[ "$name" =~ ^[0-9a-z]{16}$ ]]; then
echo mv "$name" "$name.txt"
fi
done
Elimínelo echo
una vez que sepa que está haciendo lo correcto.
Observe que he anclado el patrón para que los nombres más largos no coincidan. También me aseguro, con la -f
prueba, de que los nombres que obtenemos sean en realidad únicamente los de archivos normales.
Respuesta2
Conextglob
shopt -s extglob
for file in +([0-9a-z])
do
[[ ${#file} == 16 ]] && echo mv "$file" "${file}.txt"
done
+([0-9a-z])
significa uno o más[0-9a-z]
caracteres${#file}
da la longitud del nombre del archivoecho
es para funcionamiento en seco, retírelo una vez que todo esté bien
Respuesta3
Si tiene perl-rename (llamado rename
en sistemas basados en Debian, perl-rename
en otros), puede hacer:
perl-rename -n 's/^[0-9a-z]{16}$/$&.txt/' *
Si eso hace lo que desea, elimine el -n
para que realmente cambie el nombre de los archivos. La sintaxis de perl-rename
es un comando de Perl. Aquí, estamos usando el operador de sustitución ( s/from/to/
) que reemplazará from
con to
. En from
este caso, es su expresión regular y to
es la variable especial $&
que significa "lo que coincidió", más la extensión .txt
.
Para hacer esto con un globo de shell (use@Kusalanandao@Deep del Solenfoque, esto es sólo para completar):
for f in [0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z][0-9a-z]; do
mv -- "$f" "$f".txt
done
Con GNU find
:
find . -regextype posix-extended -regex '.*/[0-9a-z]{16}' -exec mv {} {}".txt" \;
Respuesta4
L16=$(csh -c 'repeat 16 echo -n "?"')
find . -name "$L16" ! -name '*[!0-9a-z]*' -exec sh -c '
mv "$1" "$1.txt"
' {} {} \;