Linux | Копировать только 100 лучших новых файлов в каталоге и вложенных каталогах

Linux | Копировать только 100 лучших новых файлов в каталоге и вложенных каталогах

У меня есть хранилище, похожее на следующее на AzureVM/Ubuntu

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

Поскольку объем данных очень велик для вычислений и выполнения любых операций с ними, я хочу взять образец этих данных, чтобы разработать свой код анализа данных.

Я хочу скопировать подмножество в другое место, в котором содержится 100 новейших файлов в каждом каталоге и вложенном каталоге, а также все файлы в корне, что-то вроде этого.

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

Я попробовал несколько команд на основе cp, но ни одна из них не работает и выполняется слишком долго.

Может ли кто-нибудь мне здесь помочь?

решение1

Обычно вы можете разделить это на три задачи, где вы начинаете со структуры каталогов, а затем, как в вашем случае, ограничиваете количество файлов до 100. Последняя часть инвертируетсоответствоватьдля охвата остальных файлов.

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

решение2

Это можно легко сделать с помощью выборочного архивирования. Вы можете заархивировать файлы (только нужные) и затем извлечь tarball куда-нибудь еще. Я предполагаю, что ваши файлы журналов имеют те же имена, за исключением нумерации (например, log1, log2 и т. д.). Таким образом, первые сто файлов можно определить в команде tarball как log{1..100}. Например:

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

При извлечении исходная структура файла будет воссоздана в новом месте. Поэтому вам может понадобиться использовать опцию "--strip-components=" для усечения избыточных ведущих каталогов, чтобы избежать беспорядка.

Связанный контент