Linux | Copie solo los 100 archivos nuevos principales en el directorio y directorios anidados

Linux | Copie solo los 100 archivos nuevos principales en el directorio y directorios anidados

Tengo un almacenamiento similar al siguiente en AzureVM/Ubuntu

-/A
   -/B --> 10000 log files
   -/C --> 100000 log files 
      -/D --> 200000 images 
   summary.xml
   -/data --> 1000 csv files

Ahora bien, como el tamaño de los datos es muy grande para calcularlos y realizar cualquier operación allí, quiero tomar una muestra de estos datos para desarrollar mi código de análisis de datos.

Quiero copiar un subconjunto a una ubicación diferente que tenga los 100 archivos más nuevos en cada directorio y directorio anidado y todos los archivos en la raíz, algo como esto.

-/New_Location
   -/B --> 100 log files
   -/C --> 100 log files 
       -/D --> 100 images 
   summary.xml
   -/data --> 100 csv files

Probé varios comandos basados ​​en cp pero nada funciona para mí y me lleva demasiado tiempo ejecutarlo.

¿Alguien puede ayudarme aquí?

Respuesta1

Generalmente puedes dividir esto en tres tareas, donde comienzas con la estructura del directorio y luego, como en tu caso, limitas los archivos a 100. La última parte invierte elfósforopara ampliar el alcance del resto de los archivos.

#!/bin/bash  
  
# Example START  
[[ ! -d A/ ]] && { \  
mkdir -p \  
A/{tmp/folder,\  
{A..Z}}/{images,data} && \  
printf %s\\0 \  
A/{summary.xml,\  
tmp/De5Loh4X.tmp,\  
{A..Z}/{{1..1000}_file.log,\  
images/{1..1000}_pic.{jpg,png},\  
data/example.csv}} | xargs -0 touch; }  
### Example END  
  
set -o noglob  
  
source=A  
target=target  
number=100  
# prune="-false"  
prune="-type d -path $source/tmp -prune"  
match='-name *.log -o -name *.jpg -o -name *.png'  
  
echo Create directory structure.  
find "$source" \  
\( $prune -o -type d -links 2 \) -printf %P\\0 | cpio -0 -pvdm -D "$source" "$target"  
  
  
echo Copy 100 files.  
while IFS= read -rd ''; do  
find "$REPLY" \  
-maxdepth 1 -type f \( $match \) -printf '%T@\t%P\0' | sort -zk1rn | cut -zf2- | head -zn $number | cpio -0 -pvdm -D "$REPLY" "$target/${REPLY/#$source\//}"  
done < <( \  
find "$source" \  
\( $prune -false -o -type f \) -printf %h\\0 | sort -zu \  
)  
  
echo Copy everything else.  
find "$source" \  
\( $prune -false -o -type f ! \( $match \) \) -printf %P\\0 | cpio -0 -pvdm -D "$source" "$target"

Respuesta2

Esto se puede hacer fácilmente mediante un archivado selectivo. Puede guardar los archivos (solo los deseados) y luego extraer el archivo tar en otro lugar. Supongo que sus archivos de registro tienen el mismo nombre excepto por la numeración (por ejemplo, log1, log2, etc.). Por lo tanto, los primeros cien archivos se pueden definir en el comando tarball como log{1..100}. Por ejemplo:

tar -cvf copied.tar <path1>/log{1..100} <path2>/log({1..100}etc.

Cuando extraiga, la estructura del archivo original se recreará en la nueva ubicación. Por lo tanto, es posible que necesites usar la opción "--strip-components=" para truncar los directorios principales redundantes y evitar el desorden.

información relacionada