Excluindo arquivos com o mesmo nome em vários diretórios no bash

0

Usando a linguagem bash com a arquitetura a seguir

 - directory1
        - entries
 - directory2
        - entries

Eu quero excluir as entradas duplicadas e manter apenas uma delas. Eu estou usando o seguinte script:

for dir in *
do 
    [ -d "$dir" ] && for file in "$dir"/*
    do 
        filename=$(basename "$file")
        find . -name "$filename" -not -path "*$dir*" -exec rm "{}" \;
    done
done

O problema que enfrento é que, quando um diretório é esvaziado, filename="*" . Portanto, find retornará todas as entradas e excluirá tudo.

Não consigo usar nenhuma ferramenta, pois a máquina que estou usando não pode acessar a Internet.

    
por user3714670 05.10.2016 / 17:48

2 respostas

0

Com sua solução, não vejo como você mantém um . Se o arquivo 'f' estiver nos diretórios 'A' e 'B':

  • quando o loop externo for em 'A', o resultado será impresso em B / f.
  • ------------------------------- 'B', ------------ ------- A / f.

No entanto, você não faz nada, apenas imprime.

Eu proponho isso, sem aninhar um achado em um for em a:

there_can_be_only_one.sh:

#!/bin/sh
tmp=$(mktemp -d)
dir=$1

for d in "$dir"/*; do
  if [ -d "$d" ]; then
    for f in "$d"/*; do
      bf=$(basename "$f")
      if [ -a "${tmp}/$bf" ]; then
        rm "$f"
      else
        touch "${tmp}/$bf"
      fi
    done
  fi
done

rm -rf "$tmp"

Basicamente, um novo diretório temporário (n vazio), $ tmp, é criado. Então, para cada arquivo $ f, se $ tmp contiver um arquivo com o mesmo nome de arquivo, então remova aquele arquivo $ f else crie um arquivo com aquele nome de arquivo em $ tmp.

yarl@badaboum:~/work$ ls
foo  there_can_be_only_one.sh
yarl@badaboum:~/work$ ls -R foo/
foo/:
dir0  dir1  dir2

foo/dir0:
de  hello  mammouth

foo/dir1:
arg  de  heart  hello

foo/dir2:
arg  blarg  de

yarl@badaboum:~/work$ ./there_can_be_only_one.sh foo/
yarl@badaboum:~/work$ ls -R foo/
foo/:
dir0  dir1  dir2

foo/dir0:
de  hello  mammouth

foo/dir1:
arg  heart

foo/dir2:
blarg
    
por 06.10.2016 / 13:18
0

A adição do teste a seguir resolveu o problema:

for dir in *
do 
    [ -d "$dir" ] && [ "$(ls -A $dir)" ] && for file in "$dir"/*
    do 
        filename=$(basename "$file")
        find . -name "$filename" -not -path "*$dir*" -exec rm "{}" \;
    done
done
    
por 06.10.2016 / 11:34