Es simple. No puedo soportar cuando la gente usa espacios al nombrar archivos. A veces destruye los comandos de la consola y hace que la salida de ls sea fea.
El desafío es escribir un programa (solo caracteres ascii) que
- cambia el nombre de todos los archivos (incluidos los directorios) en el directorio actual a versiones con espacios eliminados o reemplazados por '_'
- en caso de colisión, debe agregar un identificador único (depende de usted)
- desciende recursivamente en todos los subdirectorios
Puede asumir nombres de ruta de estilo UNIX. ¿Quién necesitaría este programa en una máquina Windows de todos modos?
Este es el código de golf, el programa más corto gana (#ascii caracteres). Como odio tanto los espacios, cada espacio tiene que contarse dos veces.
Proporcione su idioma, puntaje, programa y una breve descripción de cómo ejecutarlo.
El programa debe compilarse y ejecutarse con un esfuerzo razonable en mi máquina Linux.
EDITAR: como Etan solicitó una estructura de archivos para las pruebas, aquí está el script que utilizo actualmente para crear un árbol de archivos adecuado:
#!/bin/bash
rm -r TestDir
touchfiles()
{
touch my_file
touch my__file
touch "my file"
touch "my file"
touch " my_file "
}
mkdir TestDir
cd TestDir
touchfiles
for dir in "Test Sub" Test_Sub "Te stSub" Te_stSub
do
mkdir "$dir"
cd "$dir"
touchfiles
cd ..
done
fuente
Respuestas:
Coreutils Zsh + GNU - 48 bytes (1 espacio)
Es extraño que odies los espacios (ASCII), pero estás bien con pestañas y líneas nuevas, pero supongo que se necesita todo tipo.
zmv resuelve muchos problemas de cambio de nombre de archivos de manera concisa (y solo un poco oscura). Sin embargo, insiste en que los objetivos sean únicos; Si bien puede agregar fácilmente sufijos únicos, agregar un sufijo solo si fuera necesario prácticamente requiere volver a hacer todo el trabajo. Entonces, en cambio, hago un bucle manualmente y confío en GNU mv para agregar un identificador único en caso de colisión (
--backup
opción, más--no-target-directory
en caso de que un destino sea un directorio existente, ya que demv
lo contrario se movería la fuente dentro de ese directorio).(od)
es un calificador global para ordenar la salida con directorios que aparecen después de su contenido (como los de find-depth
).D
incluye archivos de puntos en el globo.:h
y:t
son modificadores de historia similares adirname
ybasename
.mv
se queja de que se llama para cambiar el nombre de los archivos a sí mismos, porque el globo incluye nombres de archivos sin espacios. Así es la vida.Versión sin golf:
fuente
zmv
bombas antesmv
tienen la oportunidad de resolver las colisiones. Ok, estoy haciendo esto manualmente. Resulta que tiene exactamente la misma longitud si me salto los archivos de puntos e incluso guarda un carácter si no lo hago.Bash 116 bytes, 16 espacios
No suprimí los errores para ganar un par de bytes más. Esto no tendrá ninguna colisión.
Si
find
se puede esperar GNU no posix , esto se puede acortar aún más:Bash 110 bytes, 15 espacios
Eliminar espacios en lugar de reemplazarlos usa dos bytes menos:
Bash 108 bytes, 15 espacios
Nota: si se pueden usar pestañas en lugar de espacios, solo se necesita 1 espacio (el que está en la regla de coincidencia para la sustitución en la línea 2).
Gracias a Dennis por encontrar un error en la comilla doble (y proporcionar una solución)
fuente
-depth
en GNU puede ser reemplazado por-d
, aunque se queja de que está en desuso. No sé sobre las reglas del golf, ¿puedo hacer eso?bash -c 'B=${0##*/}...' {} \;
en su lugar, que en realidad es más corto.N
variable? Nunca se define ...Python 180 bytes
solo 2 espacios si usa tab para sangría :-)
fuente
Si el orden de los sufijos de archivos colisionados no necesita dar precedente al archivo preexistente, entonces lo siguiente funciona para mí:
bash / find / mv 84 bytes, 16 espacios
bash / find / mv 82 bytes, 14 espacios
Acurrucado
&&
para ahorrar dos bytes de espacio.bash / find / mv 60 bytes, 11 espacios
Elimina la protección contra errores para obtener errores de mv en archivos que no tienen espacios para comenzar.
Editar: se eliminaron las citas
{}
según lo recordó Dennis. También se lefind
permite gritar sobre portabilidad y desaprobación en la versión más corta dondemv
ya se está gritando sobre mover un archivo encima de sí mismo.Edición 2: se agregó
-T
almv
comando para evitar anidar directorios en lugar de renombrar como lo señala pqnet. Se usó la expansión de llaves al costo de un personaje sobre el uso de un solo espacio.fuente
-d
lugar de-depth
y no necesita las comillas{}
.-d
conversación sobre la respuesta de pqnet pero pensé que, dado que estaba silenciando losmv
gritos, evitaría losfind
gritos. Aunque probablemente debería acortarlo por el grito. Y sí, siempre cito{}
por alguna razón, aunque sé que no tienes que hacerlo en este caso. Fuerza de la costumbre, supongo.-T
opción paramv
evitar estoNodeJS - 209 bytes, 3 espacios en blanco
fuente
node file.js
TypeError: Object #<Object> has no method 'exists'
. Adivina dónde: ¡está en la línea 1! : DBash - 86 bytes
fuente
--backup
a--b
Bash + Perl
rename
64(
rename
es el script de Perl en Debian y derivados, no el comando util-linux).fuente
*
debería ser{}
, tal como está, esto solo cambia el nombre de los archivos cuyo nombre aparece en el directorio actual. Esto no agrega un sufijo en caso de colisión. Podría ahorrar bastante omitiendo,-name "* *"
ya querename
ignora silenciosamente los archivos cuyo nombre no se transforma.POSIX
sh
+ GNUfind
+ GNUmv
67 bytes ASCII + un espacio (literal)No sé si encaja, pero con esto cualquier secuencia de espacios se elude a una sola
_
, me gusta de todos modos. En realidad, cualquier secuencia, excepto los espacios iniciales / finales, es decir, se trunca automáticamente (lo que también es, creo, un comportamiento beneficioso) . Gracias a Gilles por señalar esto.Esto solo usa el separador de campo interno para separar los campos.
Es bastante ... hablador ...
...Oh hombre. Sabía que la ficha era barata, pero pensé que al menos era inteligente. Ahora llego tarde a la fiesta ...
fuente
IFS
cosita mágica ...$expand
no (expandido)) y lo que acabo de mencionar. Mira aquí-exec
con-execdir
. Otra peculiaridad de laIFS
que no menciona es que los espacios finales se eliminan. Tenga en cuenta que, como otros han notado, también necesita la-T
opciónmv
, para cuando el objetivo de unamv
llamada es un directorio existente.sh -c 'mkdir -p ../newtree/"$0"; ln "$0"/* ../newtree/$0 {} \;
y otros globos en unfind -type d
comando para crear un árbol reflejado de enlaces duros y luego operar en ellos, pero supongo que escribir un código de golf para una operación de movimiento. Buen punto sobre los espacios iniciales / finales, aunque creo que también es un comportamiento que preferiría.zsh
la función integrada dezmv
por ejemplo.PHP,
147145bytes,21 espacios-> 146función recursiva. Corre con
s(".");
Recorrer los
glob
resultados para la ruta dada:fuente
Rubí 121
fuente
gam3.rb:5:in `rename': Directory not empty - ./Te stSub or ./Te_stSub (Errno::ENOTEMPTY) from gam3.rb:5 from /usr/lib/ruby/1.8/find.rb:39:in `find' from /usr/lib/ruby/1.8/find.rb:38:in `catch' from /usr/lib/ruby/1.8/find.rb:38:in `find' from gam3.rb:3
Pitón, 187
165, más 22 puntos de penalización por los espacios.
166, usando el truco \ t de Emanuele :
¡Solo un espacio en este!
fuente
LiveScript - 166
(Reemplace los espacios con pestañas).
Basado en la versión optimizada de nderscore de la respuesta de cPu1 .
fuente
Bash 4+ 111 bytes
fuente
Groovy, 139 caracteressegún el comentario de @ edc65
Groovy, manejar colisiones, 259 caracteres
fuente
POSIX (Probado en zsh) + comandos básicos de Linux 151
fuente
$(ls -CR)
Es completamente falso. La-c
opción es inútil, y-R
obtiene archivos sin su directorio, lo cual no tiene sentido. Su arquitectura fundamentalmente no manejará nombres de archivos que contengan nuevas líneas. Necesitaset -f
o de lo contrario los nombres de archivo que contienen comodines explotarán.export
es inútil Puedo ver vagamente lo que intentas hacer para uniquificar archivos, pero la tubería está mal.