Remove arquivos recursivamente com idx 10.000

0

O problema

No atual diretório de trabalho eu tenho várias (muitas) pastas e algumas delas têm muitos (como 100.000 +) arquivos dentro.

Meu objetivo é obter apenas a pasta com mais de 10.000 arquivos e excluir folderName10001.ext e acima (onde folderName é o nome real da pasta que contém e ext é uma extensão qualquer que seja ) .

Abordagem adotada

Estou tentando imprimir nameFolder numberOfFiles com bash .

find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {}; ls {} | wc -l" \;

Isso funciona muito bem (para a pasta de amostra acer ), mas a saída é

./acer
6058

Eu gostaria de ter uma saída de 1 linha por pasta

find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {} 'ls {} | wc -l'" \;

diz ls: cannot access {}: No such file or directory .

Perguntas

  1. Como posso exibir em uma linha nameFolder numberOfFiles ?
  2. Existe uma maneira mais fácil de excluir todos os arquivos folderName/folderName#.ext , com # > 10000 ?

Questão 2

Mais alguns detalhes podem ajudar a entender o que está acontecendo.

Eu tenho uma pasta com a seguinte árvore

.
├── a
│   ├── a1.ext
│   ├── a2.ext
│   ├── a3.ext
│   └── a4.ext
├── b
│   ├── b1.ext
│   ├── b2.ext
│   ├── b3.ext
│   └── b4.ext
└── c
    ├── c1.ext
    ├── c2.ext
    ├── c3.ext
    └── c4.ext

Gostaria de remover todos os arquivos com um número maior que 2 . (No meu caso específico, o limite é definido como 10000 .)

Resposta 1

É tudo sobre quem interpreta o que (graças a @Bratchley para o conselho nos comentários).

Como estou digitando em bash , bash é o primeiro a interpretar o que eu digito. Se eu quiser que bash envie para find ' bash a backtick , eu preciso escapar .

find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {} \'ls {} | wc -l;\'" \;

que me dá

./acer 6058

@Barmar aponta que single - e aspas duplas se comportam de maneira diferente e, portanto,

find . -maxdepth 1 -type d -name 'acer' -exec sh -c 'echo {} 'ls {} | wc -l'' \;

funcionaria muito bem (note " substituído por ' ).

Resposta 2

Isto foi fornecido por Walter A , e é o aceite resposta para esta pergunta.

Mais erros (seguem-se alguns exemplos) ...

black: 390120
./clean.sh: line 6: /bin/ls: Argument list too long
rm: missing operand
Try 'rm --help' for more information.

leather: 118240
./clean.sh: line 6: /bin/ls: Argument list too long
rm: missing operand
Try 'rm --help' for more information.

OK, corrigi-lo com

ls -d */ | cut -d/ -f1 | while read dir; do
COUNT=$(ls $dir | wc -l);
   if [ ${COUNT} -gt 10000 ]; then
      echo "$dir: ${COUNT}" ;
      for i in 'seq 10001 ${COUNT}'; do
         rm ${dir}/${dir}${i}.*
      done
   fi
done
    
por Atcold 03.04.2015 / 20:23

2 respostas

1

Você pode escrever

ls -d */ | while read dir; do
    echo "$dir: $(ls $dir | wc -l)"
done

Quando os nomes dos arquivos são numerados sem zeros à esquerda, você pode tentar

ls -d */ | cut -d/ -f1 | while read dir; do
     COUNT=$(ls $dir | wc -l);
     echo "$dir: ${COUNT}" ;
     if [ ${COUNT} -gt 10000 ]; then
        ls ${dir}/${dir}?????*.ext | grep -v ${dir}/${dir}10000.ext | xargs rm
     fi
done

Outra abordagem seria possível quando você tem zeros à esquerda nos nomes de arquivo:

ls -d */ | cut -d/ -f1 | while read dir; do
   ls ${dir}/${dir}*.ext | tail -n +10001 | xargs rm
done

Editar: Incluiu dir + filename em comandos ls, e eu adicionei cut -d/ -f1 | para cortar o trailing /.

    
por 03.04.2015 / 23:35
2

Use aspas simples em vez de aspas duplas, para que os backticks e $ não sejam interpretados pelo shell original:

find . -maxdepth 1 -type d -name 'acer' -exec sh -c 'echo {} $(ls {} | wc -l)' \;

Para a segunda pergunta, gostaria de colocar o que você quer fazer em um script separado, que leva o nome do diretório como um argumento. Então faça:

find . -maxdepth 1 -type d -name 'acer' -exec ./scriptname {} \;

Dessa forma, você não precisa lidar com todos os problemas de citação usando -exec sh -c .

    
por 03.04.2015 / 22:11