Listar apenas arquivos exclusivos com base no nome de arquivo parcial

2

Por exemplo, eu tenho muitos arquivos que se parecem com a saída abaixo, estou tentando obter uma lista de todos os nomes de arquivos exclusivos, mas desconsidere os caracteres à direita do "-". Eu tentei ls -la | grep ....- | sort --unique e algumas variações, mas isso não dá a saída que eu preciso

4855-00160880.psi
4855-00160980.ps
4855-00160980.psi
5355-00160880.ps
5355-00160880.psi
5355-00160980.ps
5355-00160980.psi
5855-00160880.ps
5855-00160880.psi
5855-00160980.ps
5855-00160980.psi
5855-00160A80.ps
5855-00160A80.psi

Idealmente, gostaria que a saída mostrasse algo como

4855
5355
5855
    
por sealfab 28.04.2017 / 19:38

4 respostas

5

Como é isso?

printf "%-4.4s\n" ????-* | uniq

O shell expande o curinga em ordem alfabética e passa o resultado como argumentos para printf . A string de formato trunca cada argumento para quatro caracteres e adiciona uma nova linha. Agora tudo o que resta é remover duplicatas adjacentes.

Se você não sabe o número de dígitos antes do hífen, mas tem uma ideia, pode passar por cima de alguns candidatos:

for expr in '??' '???' '????' '?????'  # Quoted (!)
do
    printf "%-${#expr}.${#expr}\n" $expr-* |  # Unquoted!
    uniq
done

Isso usa a expansão de parâmetro do Bash. que obtém o comprimento da string de $[#var} .

Observe o truque de citar os curingas para evitar sua expansão na inicialização do loop, usando a variável não citada dentro do loop (que é um não-não na maioria dos outros casos).

    
por 28.04.2017 / 21:28
2

Como você realmente não quer analisar ls , isso deve faça o truque:

find . -type f -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
    
por 28.04.2017 / 19:46
1

com zsh :

myfiles=(*-*(.))
print -rl -- ${(u)myfiles[@]%%-*}

Isso salva todos os nomes de arquivo regulares que contêm pelo menos um traço em uma matriz. Em seguida, ele usa a expansão de parâmetro em cada elemento da matriz para remover o primeiro traço e tudo o que segue. Quaisquer elementos duplicados são removidos por meio do sinalizador (u) .
Para selecionar arquivos ocultos também, use myfiles=(*-*(.D))

    
por 28.04.2017 / 22:51
0

Vale a pena adicionar -type f à resposta do DopeGhoti, para evitar o falso resultado . .

find . -maxdepth 1 -exec basename "{}" \; | cut -d'-' -f1 | sort -u
.
4855
5355
5855
find . -maxdepth 1 -type f -exec basename "{}" \; | cut -d'-' -f1 | sort -u
4855
5355
5855
$

Se você deseja manter uma aparência semelhante à sua tentativa original, você pode usar isso (ruim, já que ele analisa ls !)

ls -1 | grep ^....-  | cut -c1-4 | sort --unique

solução baseada em awk, ainda analisando ls

ls -1 | awk -F- '{print $1}' | sort --unique

Não há necessidade real de classificar em cada um desses casos, pois ls output já está classificado, portanto, é possível usar apenas uniq .

ls -1 | awk -F- '{print $1}' | uniq

solução baseada em sed

ls -1 | sed 's/-.*//' | uniq

encontrar uma solução / sed que evite analisar ls

find . -type f -printf "%f\n" | sed 's/-.*//g' | sort --unique

Se sempre 4 dígitos antes do "-" então isso é bem elegante

find . -type f -printf "%.4f\n" | sort -u
    
por 28.04.2017 / 21:08

Tags