Digamos que tengo un montón de archivos en un directorio.
filename-1.ext1
filename-1.ext2
filename-1.ext3
filename-2.ext1
filename-2.ext2
filename-2.ext3
filename-3.ext1
filename-3.ext2
filename-3.ext3
Luego quiero crear subdirectorios en el mismo directorio con el mismo nombre que los archivos (nombre de archivo pero sin extensión) y moverlos así
filename-1
├──filename-1.ext1
├──filename-1.ext2
└──filename-1.ext3
filename-2
├──filename-2.ext1
├──filename-2.ext2
└──filename-2.ext3
filename-3
├──filename-3.ext1
├──filename-3.ext2
└──filename-3.ext3
¿Cuál sería la forma más eficiente de lograr esto?
Editar: ext1, ext2, ext3 son solo para indicar tres nombres de archivos distintos, como .foo, .bar, .top, .coffee, etc. No es que los nombres de archivos sean similares.
Respuesta1
Como estás usando zsh
, esto podría hacerse así:
for name (*.ext<->(.)) mkdir -p -- $name:r && mv -- $name $name:r
o usando la forma larga más familiar del for
bucle,
for name in *.ext<->(.); do
mkdir -p -- $name:r &&
mv -- $name $name:r
done
Esto itera sobre todos los archivos normales que coinciden con el patrón *.ext<->
donde <->
coinciden con cualquier número. Es el calificador global (.)
que impone la coincidencia sólo de archivos normales. Cambie todo el patrón *.*(.)
si desea que coincida con el nombre de cualquier archivo normal que contenga un punto; Requerimos que el punto esté presente ya que desea eliminar una extensión de nombre de archivo más adelante. Para utilizar un patrón más estricto en lugar de más flexible, utilice algo como filename-<->.ext<->(.)
. Este patrón requiere que sepas que deseas hacer coincidir nombres que comiencen con la cadena filename-
.
La $name:r
expansión dará como resultado el mismo valor que $name
, pero sin la extensión (es decir, sólo la "raíz" del valor).
Se utiliza --
para señalar el final de las opciones a ambos mkdir
y mv
evitar que los nombres que comienzan con un guión se confundan con opciones.
Respuesta2
Con zmv
:
autoload -Uz zmv # best in ~/.zshrc
mkmv() { mkdir -p -- $2:h && mv -- "$@"; }
zmv -P mkmv -n '(*).ext<->(#q.)' '$1/$f'
(eliminar -n
cuando esté satisfecho).
De esa manera, se beneficiará de zmv
los controles de cordura de.
Respuesta3
Utilice este for
bucle que es compatible con los shells bash y zsh:
for file in *.*; do
[ -f "$file" ] &&
mkdir -p -- "${file%.*}" &&
mv -- "$file" "${file%.*}/"
done
-p
La opción enmkdir
se asegura de que el archivo exista no genera un error.%.*
elimina la extensión de los nombres de archivos.
Respuesta4
Con GNU paralelo (una herramienta de la que recién estoy empezando a darme cuenta del poder):
ls | parallel 'mkdir -p {.}; mv -i {} {.}'
Como esto no está vinculado a la CPU de ninguna manera, supongo que parallel
no brindará ninguna ventaja de velocidad, pero aún así es más corto que muchas de las otras soluciones dadas.
Y esto no depende del patrón de nombres de archivos.