Como obter o diretório com o maior índice e eliminar os diretórios restantes?

2

Eu tenho um processo que cria progressivamente diretórios, atribui um índice em ordem crescente para eles e armazena os resultados no diretório da última iteração, aquele com o maior índice. Como o número de iterações necessárias para concluir o processo varia de acordo com o conjunto de dados, não posso prever o índice do último diretório. Por exemplo:

#Dataset 1 may produce
ls -d Dir*
...    Dir4    Dir5

e

#Dataset 2 may produce
ls -d Dir*
...    Dir34    Dir35

Eu imaginei que eu poderia criar e Array que contém o nome de todos os diretórios, fazer uma cópia do último e remover todos os Diretórios

ARR=($(ls -d Dir*))
cp ${ARR[@]:(-1)} LastDirectory #Preserve my results in LastDirectory
rm Dir*

Mas esta é uma maneira de me atirar no pé. Digamos que o programa leve dez iterações para terminar. Então, Dir10 conterá meus resultados. Se eu listar os diretórios e passá-los para o array, Dir10 não estará na última posição e será eliminado. Este é o tipo de comportamento imprevisível que eu quero evitar!

#You can copy-paste this piece of code to replicate the problem:
mkdir Dir1 Dir2 Dir3 Dir4 Dir5 Dir6 Dir7 Dir8 Dir9 Dir10 
ls -d Dir*
Dir1 Dir10 Dir2 Dir3 Dir4 ... Dir8 Dir9
ARR=($(ls -d Dir*))
echo ${ARR[@]:(-1)}
Dir9

Existe uma maneira de salvar todos os diretórios, exceto aquele com o maior índice?

OBSERVAÇÃO: Eu pensei em usar as datas de criação de diretórios, mas parece que essa opção não é suportada no Linux.

    
por je_b 08.09.2016 / 16:20

5 respostas

4

No meu Ubuntu existe a opção -v para ls . De man ls :

-v natural sort of (version) numbers within text

Como alternativa, a opção -V para sort também serve para lidar com números de versão. Decidi incluí-lo na minha resposta porque sort funciona como um filtro. Pode ser útil no caso geral (por exemplo, quando você obtém sua lista de diretórios de find ou de um arquivo de texto).

Escreva sua definição de array assim:

ARR=($(ls -d -v Dir*))

ou isto:

ARR=($(ls -d Dir* | sort -V))

EDIT: o comentário de dave_thompson_085 dá uma simplificação útil:

adding -r to either puts the desired item first, accessible with more convenient ${ARR[1]}.

    
por 18.09.2016 / 14:12
0

Você pode (manualmente) criar um diretório chamado Dir1000 antes iniciar o processo e, em seguida, criar Dir1001 , Dir1002 etc.?
Se o processo funcionar dessa maneira, seria óbvio e fácil?

    
por 21.09.2016 / 05:02
0

Como você não pode alterar o programa que cria os diretórios, como você mencionou, você pode fazê-lo gravar em diretórios de saída diferentes para cada tarefa? Então você teria

Task1
+ Dir1
+ Dir2
Task2
+ Dir3
+ Dir4

Caso contrário, é provavelmente mais seguro ver os conteúdos dos diretórios. Existem diferenças entre os diretórios intermediários e o último que contém os resultados? Se os resultados estiverem apenas no último diretório, você pode usar essa informação para descobrir qual é copiar os resultados e remover os outros diretórios.

    
por 22.09.2016 / 13:46
0

O sort tem as opções -n -r e -k ? Em caso afirmativo, use:

ARR=($( ls -d Dir* | sort -rn -k1.4 ))

Para testar o resultado, use:

mkdir Dir1 Dir2 Dir3 Dir4 Dir5 Dir6 Dir7 Dir8 Dir9 Dir10 Dir20 Dir100
ARR=($( ls -d Dir* | sort -rn -k1.4 ))
echo ${ARR[@]}

O resultado deve ser:

Dir100 Dir20 Dir10 Dir9 Dir8 Dir7 Dir6 Dir5 Dir4 Dir3 Dir2 Dir1

Para salvar o diretório com o maior índice e remover o restante deles (assumindo que LastDirectory não existe), use:

mv ${ARR[0]} LastDirectory # or simply mv $ARR LastDirectory
rm -r Dir* # error if only one Dir* directory, but LastDirectory is preserved

O comando sort -nr -k1.4 usa a opção -k para classificar os nomes de diretório usando o quarto caractere para o último caractere, ignorando os três primeiros caracteres. A opção -n é classificada numericamente e a opção -r inverte a ordem para que o maior número seja o primeiro.

Uma nota sobre robustez, isto é, lidar com condições inesperadas. A solução assume que all os nomes correspondem ao padrão onde há três caracteres, " Dir ", seguido por um número e que LastDirectory não existe. Em geral, o comando ls é problemático porque lista os nomes de uma maneira fácil de ler; mas, por exemplo, se um nome de arquivo tiver um espaço incorporado (caractere em branco), o nome quebraria essa solução de maneiras imprevisíveis.

    
por 22.09.2016 / 16:43
0

Se você está certo em classificar os diretórios por data (parece que o diretório com o índice mais alto também é o mais recentemente criado), você pode fazer isso:

ls -1td Dir* | tail -n +2

que lista todos, exceto o diretório mais recente. Para excluir esses:

rm $(ls -1td Dir* | tail -n +2)

O argumento chave aqui é -t , que classifica por data.

    
por 23.09.2016 / 21:02

Tags