Así que, impaciente, utilicé el siguiente script en mi servidor 19.04 en un intento de mover un montón de archivos de video a carpetas con prefijos:
dirs=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
shopt -s nocasematch
for file in *
do
for dir in "${dirs[@]}"
do
if [ -d "$file" ]; then
echo 'this is a dir, skipping'
break
else
if [[ $file =~ ^[$dir] ]]; then
echo "----> $file moves into -> $dir <----"
mv "$file" "$dir"
break
fi
fi
done
done
No tengo idea de dónde salió mal, pero en lugar de mover los archivos a las carpetas fue a una salida singular ... entonces:
----> a1.ts moves into -> A <----
----> a2.ts moves into -> A <----
----> a3.ts moves into -> A <----
----> a4.ts moves into -> A <----
----> a5.ts moves into -> A <----
----> c1.ts moves into -> C <----
----> c2.ts moves into -> C <----
----> c3.ts moves into -> C <----
----> c4.ts moves into -> C <----
----> c5.ts moves into -> C <----
Afortunadamente detuve el proceso (CTRL + C) tan pronto como noté que no iba como estaba previsto y no revisé toda la carpeta.
Así que ahora tengo esos archivos A
y C
, que son menos de un GB, y por lo que parece son un solo video.
Hay 50 Gb no contabilizados en el uso total del disco de la carpeta en sí, pero el espacio total en disco de la computadora se ha mantenido igual. ¿Me haces pensar que los archivos no se eliminan?
Cualquier ayuda apreciada, gracias :)
Editar: los archivos se han ido, solo queda el último archivo que se escribió, todo lo que tomó fue un tiempo para que el disco usara la información para actualizar ... la moraleja de la historia, ¡ejecute sus scripts en archivos simulados antes!
fuente
A
,B
etc., antes de ejecutar el script? Si no, simplemente cambió el nombre de los archivos. Todos los archivos cuyos nombres comenzaron cona
oA
han sido renombradosA
, por lo que solo sobrevivió el último archivo renombrado, los demás se sobrescriben. ¡Llamar a una variabledir
no crea un directorio!mv "$file" "$dir/"
, con un final/
; entonces, si$dir
no existe, semv
producirá un error en lugar de cambiar el nombre$file
a$dir
. También consideremv -i
ymv -n
. Y siempre haz unamkdir -p
antes de mudarte, por si acaso.Respuestas:
Creo que este es el problema: debería haber creado los directorios A, B, C ... Z. Si lo hizo, el
mv
comando debería haber movido los archivos a esos directorios.Pero si no, el
mv
comando mueve los archivos a archivos con esos nombres, A, B, C ... y creo que esto es lo que hiciste.Para que el shellscript sea más seguro, debe hacer que cree los directorios (si aún no están allí) antes de comenzar a moverlo.
Si desea que las cosas sean aún más seguras, también puede usar
mv
la-i
opciónfuente
touch
Agregar sería un buen sustituto paramkdir
evitar conflictos en caso de ejecutar el script varias veces?touch
crea un archivo si el nombre no existe. Por lo tanto, no hará lo que quieras en este caso.mkdir -p
puede manejar el uso del script varias veces.mv
más seguro es adquirir el hábito de agregar una barra diagonal al nombre del objetivo cuando el objetivo es un directorio, es decirmv "$file" "$dir/"
@Sudodus ya explicó lo que salió mal, pero aquí hay una versión más simple de su script para la próxima vez:
Explicación
for letter in {a..z}; do
: se{a..z}
expande a todas las letras minúsculas entrea
yz
:Entonces esto iterará sobre todas las letras minúsculas, guardando cada una como
$letter
.dir=${letter^}
: la sintaxis${var^^}
devuelve el contenido de la variable$var
con el primer carácter en mayúscula (ya que este solo tiene un carácter, eso es todo lo que necesitamos). Entonces, si$letter
esa
, entonces${letter^^}
esA
, y por$dir
lo tanto será la versión en mayúscula de la actual$letter
.mkdir -p -- "$dir"
: crea el directorio. Si ya existe, no haga nada (-p
). El--
significa el final de las opciones , y es útil para proteger contra los nombres que comienzan con-
.mv -- "$letter"* "${letter^}"* "$dir"
: mueve cada archivo (o directorio) al objetivo relevante.El problema con esto es que también moverá cualquier directorio que pueda tener. No moverá los directorios de destino, porque aún no existen, o intentará moverlos dentro de sí mismos, pero cualquier directorio existente que no sea el directorio de destino se moverá.
Si eso es un problema, tendrá que hacer algo como esto:
fuente
${letter^}
y${letter^^}
, y si son idénticos, por qué usar${letter^^}
en lugar de$dir
?${var^}
escribe en mayúscula solo la primera letra, mientras que${var^^}
escribe en mayúscula todas las letras. Aquí no hace ninguna diferencia, ya que$letter
solo tiene una letra.$dir
en elmv
comando. (En su forma actual fallará si un archivo preexiste con un nombre en mayúscula de una letra)En lugar de verificar cada archivo con una matriz de diccionario que crea una gran cantidad de iteraciones, puede hacer coincidir archivos con patrones.
Tipo muy básico:
fuente
Salvaguardar en su .bashrc:
fuente
-n Do not overwrite an existing file. (The -n option overrides any previous -f or -i options.)
que, ¿importa que la etiqueta -n esté antes de seguir las etiquetas? Los = --backup numeradas va a crear un doble de cada derecho, no es que un (terabytes hablando) poco exagerado (y la energía espacio / consumir) cuando se trata de archivos de vídeo súper-grande es. Gracias !Para el registro, algunas formas de evitar
mv
sobrescribir los archivos existentes:Si desea moverse a un directorio, agregue una barra diagonal al objetivo, es decir, use en
mv "$file" "$dir"/
lugar demv "$file" "$dir"
. Si$dir
no existe o no es un directorio,mv
se quejará:Esto parece hacer que el sistema llame
rename("a", "z/")
, por lo que debe estar a salvo de vulnerabilidades de tiempo de verificación a tiempo de uso, en caso de que alguien esté manejando el mismo conjunto de archivos al mismo tiempo.Alternativamente, use
mv -t "$dir" "$file"
. Nuevamente, se quejará si$dir
no es un directorio.Use la
-n
opción para evitar sobrescribir archivos existentes:No impedirá que cambie el nombre del primer archivo, pero no lo eliminará con los demás.
Esto parece ser simple
rename()
, por lo que podría no ser seguro con el manejo simultáneo. (Hayrenameat2()
que admitiría una bandera para evitar sobrescribir).fuente
Si bien aparentemente no es el caso para usted, es posible que pueda hacer esto y no perder los archivos. Esto requeriría una de dos cosas para ser verdad:
Los sistemas de archivos Unix permiten que más de una entrada de directorio haga referencia al mismo contenido de archivo . Esto se llama un ' enlace duro '. Puede crear enlaces duros con el
ln
comando, sin la-s
opción común (suave / simbólica). Mientras exista al menos un enlace duro al contenido del archivo, el sistema de archivos no lo reutilizará.(Nota al margen, los permisos generalmente se aplican al contenido del archivo, no a la entrada del directorio. Esta es la razón por la cual un usuario común a veces puede eliminar un archivo de su propiedad
root
, pero no escribir en él. La operación de eliminación modifica la carpeta, no el archivo en sí. )El sistema de archivos tampoco reutilizará el contenido del archivo siempre que al menos un proceso tenga el archivo abierto. Incluso si no existe una entrada de directorio, el sistema de archivos no considerará que el espacio esté libre hasta que ningún proceso lo tenga abierto. El archivo puede recuperarse del sistema
/proc/<pid>/fd
de archivos virtualroot
mientras el archivo permanezca abierto. (Gracias @fluffysheap).fuente