Exclui todos os arquivos que NÃO possuem nomes duplicados?

0

Dada uma grande lista de arquivos, contendo o seguinte:

FILE1.doc
FILE1.pdf
FILE2.doc
FILE3.doc
FILE3.pdf
FILE4.doc

Existe um comando de terminal que me permita remover todos os arquivos que não tenham um nome duplicado na lista? Neste caso ... FILE2.doc e FILE4.doc?

    
por antonpug 16.07.2015 / 06:46

3 respostas

1

Usando o bash, isso removerá todos os arquivos que não tiverem outro arquivo com o mesmo nome, mas extensão diferente:

for f in *; do same=("${f%.*}".*); [ "${#same[@]}" -eq 1 ] && rm "$f"; done

Essa abordagem é segura para todos os nomes de arquivos, mesmo aqueles com espaço em branco em seus nomes.

Como funciona

  • for f in *; do

    Isso inicia um loop sobre todos os arquivos no diretório atual.

  • same=("${f%.*}".*)

    Isso cria uma matriz bash com os nomes de todos os arquivos com o mesmo nome de base.

    $f é o nome do nosso arquivo. ${f%.*} é o nome do arquivo sem sua extensão. Se, por exemplo, o arquivo for FILE1.doc , ${f%.*} será FILE1 . "${f%.*}".* é todos os arquivos com o mesmo nome de base, mas qualquer extensão. ("${f%.*}".*) é uma matriz bash desses nomes. same=("${f%.*}".*) atribui a matriz à variável same .

  • [ "${#same[@]}" -eq 1 ] && rm "$f"

    Se houver apenas um arquivo com esse nome de base, o excluiremos.

    "${#same[@]}" é o número de arquivos na matriz same . [ "${#same[@]}" -eq 1 ] é verdadeiro se houver apenas um desses arquivos.

    && é lógico e. Isso faz com que a instrução que segue, rm "$f" seja executada apenas se a instrução que a precede retornar true lógico.

  • done

    Isso marca o final do loop for .

por 16.07.2015 / 07:23
0

Suponha que sua lista de arquivos esteja em algum arquivo /tmp/files.list , por exemplo. depois de ls * > /tmp/files.list ;

Em seguida, sort -u /tmp/files.list fornece uma lista de arquivos ordenados sem duplicar (não é necessário se você fez o ls * > /tmp/files.list acima). Você poderia processar isso com algum script awk inspirado em isso , por exemplo

sort -u /tmp/files.list | awk '{
  function basename(file) {
    sub(".*/", "", file)
    return file
  }
curfil=$0;
if (basename(curfil)==basename(prevfil)) system("rm " + curfil);
prevfil=curfil;
}'

Cuidado, eu não testei isso.

    
por 16.07.2015 / 07:08
0

Outra maneira simples e complexa pode ser:

for x in 'for i in *; do echo $i ; done | cut -d'.' -f1 | uniq -u '; do rm $x.*; done

Espero que seja auto-explicativo

    
por 16.07.2015 / 08:10