Tengo una carpeta que tiene más de 500 videos y el tamaño de la carpeta es de aproximadamente 80 GB.
Quiero mover 30 GB de videos a otra carpeta, pero ¿cómo?
Estoy usando una terminal y no puedo instalar una GUI.
Respuesta1
No selectivamente (automáticamente)
No conozco ninguna herramienta de línea de comandos que pueda hacer esto... Pero puedes usar un script para mover archivos hasta que se haya movido un cierto tamaño total, por ejemplo, así (Ejecute el script solo una vez... Si lo ejecuta nuevamente, moverá el tamaño especificado nuevamente de los archivos restantes.):
#!/bin/bash
sourc_dir="/path/to/directory" # Set the path to the source directory "no trailing /"
dest_dir="/path/to/directory" # Set the path to the destination directory "no trailing /"
move_size="30" # Set the total size of files to move in Gigabytes
# Don't edit below this line
move_size=$(( move_size * 1000000 ))
current_size=$(du -sk "$sourc_dir" | awk '{printf "%d", $1}')
remaining_size=$(( current_size - move_size ))
for f in "$sourc_dir"/*; do
[ -f "$f" ] || continue
new_size=$(du -sk "$sourc_dir" | awk '{printf "%d", $1}')
(( new_size <= remaining_size )) && exit
mv -n -- "$f" "$dest_dir"/
done
O incluso una sola línea (no se necesita archivo de script) que puedes ejecutar en la terminal, por ejemplo, así:
for f in /path/to/source/*; do [ -f "$f" ] || continue; (( size >= (30*(1000**3)) )) && break || (( size += $(stat --printf "%s" "$f") )) && mv -n -- "$f" /path/to/destination/; done
Es posible que desee unset size
poder volver a ejecutarlo en la misma instancia de Shell.
selectivamente (a mano)
Siempre puede especificar un patrón de shell o tubería desde una herramienta de búsqueda basada en nombres de archivos, tamaños, tipos... etc.
O, más convenientemente, puede utilizar un administrador de archivos basado en consola que admita la selección de múltiples archivos, como por ejemplo el conocido y rico en funciones.Comandante de medianoche GNUque está disponible en los repositorios oficiales de Ubuntu y se puede instalar así:
sudo apt install mc
y para ejecutarlo, escriba mc
y presione Enter... Luego se le presentará una interfaz de usuario navegable donde puede usar la Inserttecla del teclado para seleccionar varios archivos... Podrá ver el tamaño total de los archivos seleccionados y su recuento. en tiempo real así:
Una vez que haya terminado de seleccionar todos los archivos que desea mover, presione la F6tecla del teclado para abrir el cuadro de diálogo mover/cambiar nombre e ingrese el directorio de destino, luego elija [< OK >]
mover los archivos seleccionados a la vez, así:
O incluso los menos conocidos y con menos funciones.fff (Administrador de archivos jodidamente rápido):-) ... Esto está curiosamente escrito en bash
... Aunque admite la selección de múltiples archivos, es posible que necesites personalizarlo un poco para poder ver el tamaño total de los archivos seleccionados, por ejemplo, como un parche rápido, puedes cambiar la línea 159
en el archivo fuente fff
de este:
local mark_ui="[${#marked_files[@]}] selected (${file_program[*]}) [p] ->"
a esto:
local mark_ui="[${#marked_files[@]}] $(for f in "${marked_files[@]}"; do (( tsize += $(stat --printf "%s" "$f") )); done; tsize=$((tsize/(1000**2))); printf '[%d M]' "$tsize";) selected (${file_program[*]}) [p] ->"
Entonces simplemente puedes ejecutar ese archivo así (No se necesita instalación):
bash fff
O vea ayuda sobre el uso de esta manera:
bash fff -h
Luego, todo lo que tiene que hacer es simplemente navegar hasta su directorio de origen y comenzar a seleccionar archivos para mover con el m(minúscula) tecla del teclado así:
Cuando termine de seleccionar archivos, navegue hasta el directorio de destino y mueva los archivos previamente seleccionados presionando el botón p(minúscula) tecla del teclado.
Respuesta2
Aquí tienes una alternativa arafaLa idea es que no requiere un du
directorio completo para cada archivo. En lugar de eso, hace un stat
en cada archivo.una vez, usando find
's -printf
%s
para obtener el tamaño y %p
la ruta al archivo que se va a mover.
#!/bin/bash
src='foo'
dest='bar'
# 30GB in bytes to move:
(( bytestomove=30*(1000**3) ))
movedbytes=0
while IFS=$'\t' read -r -d '' bytes file
do
# if we already moved enough, break out
(( movedbytes >= bytestomove )) && break;
# try to move it, break out if it fails
mv -n -- "$file" "$dest" || break
# successfully moved, add bytes to movedbytes
(( movedbytes += bytes ))
done < <(find "$src" -type f -printf "%s\t%p\0")
(( movedmegs=movedbytes/(1000**2) ))
printf "Moved %d MB\n" $movedmegs
Respuesta3
@TedLyngmo señaló que la solución tar que presenté por primera vez copia efectivamente los archivos y no los mueve. Esta distinción es importante por 2 razones:
- Con una copia, los archivos de origen permanecen, mientras que con un movimiento, los archivos de origen ya no existen en sus ubicaciones de origen.
- Si los archivos se mueven dentro del mismo sistema de archivos, como también puede ser el caso en esta pregunta,
mv
simplemente se volverá a vincular el archivo fuente a la nueva ubicación y no se copiará el contenido en absoluto. Por lo general, esto será significativamente más rápido que copiar, especialmente para archivos grandes.
Escenario de movimiento
Todavía podemos usar los tar
conceptos del escenario de copia proporcionado originalmente para crear una lista de archivos que contenga solo los primeros 30 GB de archivos que tar
se encuentren y luego mover solo esos archivos:
#!/bin/bash
# Convert human-readable number, e.g. 1M, 30G to number of 1024 byte blocks
limit=$(numfmt --from=auto $1 --to-unit 1024)
src_dir=$2
dest_dir=$3
mkdir $dest_dir
filelist=$(readlink -f $(mktemp -p $dest_dir))
# create a list of files to be moved. tar -v outputs filenames to stdout, and
# the dest archive is /dev/null
tar -v -L $limit -F false -c -f /dev/null -C $src_dir . > $filelist 2> /dev/null
tar_result=$?
if [ "$tar_result" = 2 ]; then
echo "$1 limit was hit - some unmoved files will remain in $dest_dir"
else
echo "All files will be moved"
fi
pushd $dest_dir > /dev/null
abs_dest_dir=$PWD
# create directories in the destination
grep '/.*/$' $filelist | xargs mkdir -p
popd > /dev/null
pushd $src_dir > /dev/null
# create hard links in the destination
grep -v '/$' $filelist | xargs cp -l --parents -t $abs_dest_dir
# unlink source files
grep -v '/$' $filelist | xargs rm
# remove source directories in reverse order, if they are empty
grep '/.*/$' $filelist | tac | xargs rmdir --ignore-fail-on-non-empty
popd > /dev/null
rm $filelist
Esto es más complejo de lo que me gustaría:
mv
no ofrece tanto control de las rutas de origen y destino para múltiples archivos (específicamente no hay un análogo de lacp
opción --parents), por lo que los movimientos de archivos se logran creando enlaces físicos en las ubicaciones de destino y luego desvinculando los archivos de origen.Debido a que los directorios de origen contienen una combinación de entradas que se deben mover y que no, los directorios se deben volver a crear en el destino y no simplemente moverlos (junto con todo el contenido). Por lo tanto, los directorios de destino apropiados se crean antes de mover los archivos y los directorios de origen correspondientes se eliminan después de mover los archivos, si están vacíos.
Advertencias
tar -v
generará una entrada de archivo por línea. Esto fallará espectacularmente si hay caracteres especiales en los nombres de las rutas, por ejemplo, nuevas líneas. Esperemos que los nombres de las rutas de origen tengan nombres sensatos.Esto moverá un poco menos de 30 GB de datos de archivos reales, ya que la transmisión contiene metadatos (nombres de archivos, marcas de tiempo, etc.), así como el contenido real, y todo esto está sujeto al límite de 30 GB.
Estoy jugando un poco rápido y relajado con KB versus kb aquí. Dado que el
-L
parámetro funciona en unidades de 1024 bytes, esto en realidad limita el movimiento a 3.072.000.000 bytes de flujo tar. Ajuste los números según corresponda.filelist.txt se crea en el directorio actual. Se requerirán permisos de escritura para esto, esto probablemente sea un hecho, ya que las operaciones de movimiento requerirán permisos de escritura de todos modos.
Copiar escenario
Puede utilizar tar
para convertir su carpeta en una secuencia y luego tar
volver a convertir la secuencia en archivos en una nueva ubicación. El primero tar
utiliza -L
para limitar la "longitud de la cinta" a 3000000 KB, antes de solicitar una nueva cinta. tar
usa -F para ejecutarse false
después de cada "cinta". Debido a que false
devuelve un error, la transferencia se detiene después de la primera "cinta", es decir, 30 GB. Hacer que todos los datos pasen por solo 2 invocaciones de tar debería ser más rápido que recorrer todos los archivos con bucles bash.
mkdir dest.dir
tar -cv -L 3000000 -F false -C src.dir . | tar -x -C dest.dir/
Esto copiará los archivos hasta alcanzar el límite de 30 GB, luego el tar
correo electrónico generará un error con:
tar: Unexpected EOF in archive
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
tar: ‘false’ command failed
tar: Error is not recoverable: exiting now
tar
no transferirá el archivo que se estaba transfiriendo cuando se alcanzó el límite; no se escribirá en el destino en absoluto.
Advertencias
Esto copiará un poco menos de 30 GB de datos de archivos reales, ya que la transmisión contiene metadatos (nombres de archivos, marcas de tiempo, etc.), así como el contenido real, y todo esto está sujeto al límite de 30 GB.
Estoy jugando un poco rápido y relajado con KB versus kb aquí. Dado que el
-L
parámetro funciona en unidades de 1024 bytes, esto en realidad limita la transferencia a 3.072.000.000 bytes de flujo tar. Ajuste los números según corresponda.
Las ediciones anteriores de esta respuesta usaron find-cpio-head-cpio y luego tar-head-tar. La solución tar-tar que se presenta ahora debería ser suficiente, pero inspeccione el historial de edición si las otras soluciones son de interés.
Respuesta4
Vaya a la carpeta donde están sus archivos:
cd SOURCE_FOLDER
hacer una lista de archivos en esa carpeta
ls > list.txt
Edítalo en cualquier editor y elimina los archivos que NO quieras mover. Guarde el resultado para que ahora list.txt tenga solo los archivos que desea mover. Ahora ejecute este script simple que lee cada línea de su archivo list.txt y mueve ese archivo a su directorio de destino.
while IFS= read -r line; do mv "$line" ../DESTINATION_DIRECTORY/"$line"; done < list.txt