Linux | Copie apenas os 100 principais arquivos novos no diretório e nos diretórios aninhados

Linux | Copie apenas os 100 principais arquivos novos no diretório e nos diretórios aninhados

Eu tenho armazenamento como abaixo no AzureVM/Ubuntu

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

Agora, como o tamanho dos dados é muito grande para calcular e realizar qualquer operação, quero pegar uma amostra desses dados para desenvolver meu código de análise de dados.

Quero copiar um subconjunto para um local diferente que tenha os 100 arquivos mais recentes em cada diretório e diretório aninhado e todos os arquivos na raiz, algo assim.

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

Tentei vários comandos baseados em cp, mas nada está funcionando para mim e demorando muito para ser executado.

Alguém por favor pode me ajudar aqui?

Responder1

Normalmente você pode dividir isso em três tarefas, onde você começa com a estrutura de diretórios e em seguida, como no seu caso, limita os arquivos a 100. A última parte inverte ocorresponderpara ampliar o restante dos arquivos.

#!/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"

Responder2

Isso pode ser feito facilmente por meio de arquivamento seletivo. Você pode compactar os arquivos (apenas os pretendidos) e depois extrair o tarball em outro lugar. Presumo que seus arquivos de log tenham o mesmo nome, exceto pela numeração (por exemplo, log1, log2 etc.). Portanto, os primeiros cem arquivos podem ser definidos no comando tarball como log{1..100}. Por exemplo:

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

Ao extrair, a estrutura do arquivo original será recriada no novo local. Portanto, você pode precisar usar a opção "--strip-components=" para truncar os diretórios principais redundantes para evitar confusão.

informação relacionada