Se você tem um ambiente GNU, aqui está uma solução robusta que imprime os nomes básicos comuns, usando gawk
(apenas para misturar):
find . -maxdepth 1 -type f -printf "%ffind . -maxdepth 1 -type f -name "*.*" -printf "%ffind . -maxdepth 1 -type f -name "*.*" -printf "%ffind . -maxdepth 1 -type f -printf "%ffind . -maxdepth 1 -type f -name "*.*" -printf "%ffind . -maxdepth 1 -type f -name "*.*" -printf "%f%pre%" |
gawk 'BEGIN{ RS="%pre%" }
{ base=$0;sub(/\.[^.]+$/,"",base);seen[base][FNR]=$0}
END { for (bb in seen)
if (length(seen[bb])>1)
for (ff in seen[bb]) printf("%s%pre%",seen[bb][ff])
}' |
tr '%pre%0' '\n'
" | ...
" |
gawk 'BEGIN{RS="%pre%"} {sub(/\.[^.]+$/,""); if (length($0))printf("%s%pre%",$0)}' |
sort -z | uniq -zd |
tr '%pre%0' '\n'
" |
gawk 'BEGIN{ RS="%pre%" }
{ base=$0;sub(/\.[^.]+$/,"",base);seen[base][FNR]=$0}
END { for (bb in seen)
if (length(seen[bb])>1)
for (ff in seen[bb]) printf("%s%pre%",seen[bb][ff])
}' |
tr '%pre%0' '\n'
" | ...
" |
gawk 'BEGIN{RS="%pre%"} {sub(/\.[^.]+$/,""); if (length($0))printf("%s%pre%",$0)}' |
sort -z | uniq -zd |
tr '%pre%0' '\n'
Isso usa find
com \ 0 (nul) nomes de arquivos delimitados, gawk
com RS
(separador de registro) definido como \ 0 para corresponder à entrada e sub(/regex/)
para remover uma extensão.
O comando final tr
desfaz a delimitação nula para impressão na tela, omite isso para processamento adicional (seguro) de nomes de arquivos .
(Normalmente eu faria algo como whatever | rev | cut -d. -f2- | rev | sort
, mas rev
não faz uma entrada delimitada por nul.)
Se você quiser limitá-lo apenas a arquivos com um padrão .ext
ou mais específico, use:
%pre%
A primeira opção acima apenas imprime a base comum, se você quiser imprimir os nomes reais dos arquivos:
%pre%
(mínimo requerido do gawk v4.0 para matrizes multidimensionais!)
Isso usa uma matriz (hash) seen[]
para armazenar em cache os nomes de arquivos vistos pelo nome base e, no final, itera sobre os nomes base em seen[bb]
e imprime aqueles com mais de correspondência ( length(seen[bb])>1
).