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 acho 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, o 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?

NOTA: Pensei em usar datas de criação de diretórios, mas parece que essa opção não é suportada no Linux.

je_b
fonte
Por favor, adicione um exemplo para os índices 9 e 10.
Arjan
E não relacionado à sua pergunta, você pode usar os horários de criação em vez dos nomes.
Arjan
@Arjan eu incluí o exemplo
je_b
@Arjan Tanto quanto sei, o linux não suporta datas de criação: unix.com/shell-programming-and-scripting/…
je_b
Verdadeiro, @je_b, data de modificação então; a saída de ls -t.
Arjan

Respostas:

4

No meu Ubuntu há -vopção para ls. De man ls:

-v tipo natural de números (versão) no texto

Como alternativa, a -Vopção sorttambém se destina a lidar com números de versão. Eu decidi incluí-lo na minha resposta porque sortfunciona como um filtro. Pode ser útil no caso geral (por exemplo, quando você obtém sua lista de diretórios de findou 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: comentário dave_thompson_085 dá simplificação útil:

adicionando -ra qualquer um coloca o item desejado em primeiro lugar, acessível com mais conveniente ${ARR[1]}.

Kamil Maciorowski
fonte
1
Esses são os dois recursos do GNU coreutils que estarão em todas as distros ou builds do Linux. E adicionar -ra qualquer um coloca o item desejado em primeiro lugar, acessível com mais conveniente${ARR[1]}
dave_thompson_085
0

Você pode (manualmente) criar um dir chamado Dir1000 antes de iniciar o processo, e, em seguida, ele cria Dir1001, Dir1002etc.?
Se o processo funcionar dessa maneira, seria óbvio e fácil?

Aganju
fonte
Não posso. Eu testei sua opção e o sistema simplesmente ignora o diretório criado manualmente. Parece que o script tem seu próprio contador interno. Como uma nota lateral, este é o código que eu herdei de um colega em uma língua que eu mal entendo. Eu prefiro não tocar o que já está funcionando e resolver o problema pragmaticamente.
je_b
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 examinar o conteúdo 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ê poderá usar essas informações para descobrir qual é copiar os resultados e remover os outros diretórios.

Simon A. Eugster
fonte
0

Tem sorto -n -re -kopções? 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 LastDirectoryque 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 sort -nr -k1.4comando usa a -kopção para classificar os nomes de diretório usando o quarto caractere para o último caractere, ignorando os três primeiros caracteres. A -nopção é classificada numericamente e a -ropção 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 todos os nomes correspondem ao padrão onde há três caracteres, " Dir", seguidos por um número, e isso LastDirectorynão existe. Em geral, o lscomando é 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.

creidhne
fonte
0

Se você está bem com a classificação dos diretórios por data (parece que o diretório com o maior índice 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 excluí-los:

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

O argumento chave aqui é o -tque classifica por data.

Stefan Seidel
fonte