Como posso mover arquivos para subdiretórios por contagem? [duplicado]

3

Eu tenho cerca de 100.000 arquivos em um diretório. Como você pode imaginar, essa não é uma situação ideal e gostaria de dividir o diretório em subdiretórios. Mas os nomes de arquivos não são assim onde eu posso colocá-los em subdiretórios baseados em seus nomes ou qualquer coisa, então eu gostaria de criar, digamos, 10 diretórios e colocar cerca de 1000 arquivos em cada. Existe um comando bash ou loop fácil que faria isso?

    
por Jonathan 26.05.2016 / 01:00

2 respostas

2

Tente:

 n=0; for f in *; do d="subdir$((n++ / 1000))"; mkdir -p "$d"; mv -- "$f" "$d/$f"; done

n mantém o controle de quantos arquivos foram movidos. Em lotes de milhares, cada arquivo é atribuído a um subdiretório denominado subdir$((n++ / 1000)) . (Você pode ajustar a nomeação como quiser.) Se ela ainda não tiver sido criada, mkdir -p "$d" criará esse subdiretório. mv -- "$f" "$d/$f" transfere o arquivo para esse subdiretório.

    
por 26.05.2016 / 01:04
1

Dado o grande número de arquivos no diretório de origem, a solução proposta provavelmente levará alguns minutos.

Se você não quiser esperar, convém considerar uma solução que não gera um processo para cada movimento.

Para processar em lote, você pode utilizar o fato de que cpio com --pass-through e --link se comporta como um movimento - a origem e o destino estão no mesmo sistema de arquivos, a operação será rápida, caso contrário, uma cópia inteira será feita.

Ao contrário de mv , cpio -lpd deixará um hardlink para cada arquivo de origem, mas eles serão fáceis de remover en-mass com rm -r depois se a operação for um sucesso:

A implementação do divisor de diretório pode ser algo como:

split_dir()(
  local src=$1 nbatches=$2 dest=$3
  local tmpd=
  trap 'rm -rf "$tmpd"' EXIT
  tmpd="$(mktemp -d "$tmpd")"
  find -type f "$src" > "$tmpd/files"
  local nfiles=$(wc -l < "$tmpd/files")
  local batchsz=$((nfiles/nbatches))
  ( cd "$tmpd"; split -l "$batchsz" -d files )
  local i
  for((i=0;i<nbatches;i++)); do
    mkdir -p "$dest/$i"
    < x$i cpio -pdl "$dest/$i"
  done
)
    
por 26.05.2016 / 01:58

Tags