Altera para o último subdiretório modificado do diretório atual

2

Eu tenho um aplicativo que gera alguns arquivos em diretórios diferentes em um intervalo regular e preciso verificar os arquivos mais recentes gerados, ou seja, o arquivo que é gerado no diretório mais recente (criado ou atualizado). O nome do arquivo permanece o mesmo em todos os diretórios, então eu só quero um script simples que irá mudar o diretório para o último subdiretório modificado.

[Update] Ao ver a maioria das respostas, acho que devo esclarecer que os nomes dos diretórios são dinâmicos (depende de alguma entrada de usuário e timestamp), então não posso assumir um padrão de diretório como dir [1, 2 , 3] ou similar

    
por Jay 29.07.2014 / 10:30

4 respostas

2

Dependendo do que você quer exatamente fazer e da estrutura dos seus arquivos, outras possibilidades podem estar disponíveis, como:

ls -1tq /dir/*/readme.txt | head -n 1

Retorna o nome completo do readme.txt mais recente encontrado em qualquer subdiretório (não recursivo) de / dir /

O uso de * como parte do caminho (não apenas como parte de um nome de arquivo) muitas vezes sendo desconhecido, eu achei que valeu a pena mencionar isso.

file=$( ls -1tq /dir/*/readme.txt | head -n 1 )
cd $( dirname "$file" )
    
por 29.07.2014 / 12:38
4

Você não precisa de nenhum pipeline elaborado para isso. Além disso, você não precisa find nada - você já sabe onde cada arquivo é, você simplesmente não sabe qual deles é o mais novo. Isso é facilmente manipulado.

Para demonstração, aqui está meu pequeno teste:

mkdir ./dir1 ./dir2 ./dir3

for d in 1 2 3
do  touch ./dir$d/samefile
    sleep 1
done

Isso cria o conjunto de testes. Agora, qual é o mais novo?

set -- ./dir[123]/samefile
while [ -e "$2" ]
do  [ "$1" -nt "$2" ] && 
    set -- "$@" "$1"
shift; done
printf %s\n "$@"

Isso vai me dizer.

OUTPUT

./dir3/samefile

E eu posso mudar a ordem da operação touch tanto quanto eu quiser - ela me dará a informação correta. Tudo o que você precisa é de um pequeno loop de shell em uma função como essa:

newd() { ${2:+:} return 1
    while [ -e "$2" ] && [ -e "$1" ]
    do  [ "$1" -nt "$2" ] && 
        set -- "$@" "$1"
    shift; done
    ${2+false} cd "${1%/*}"
}

Note que isto é um pouco diferente do demo, por isso falhará com menos de dois argumentos ou se algum argumento não for um caminho real.

Agora você pode chamar assim:

newd ./path/to/file1 ./path/to/file2

... e assim por diante - com tantos argumentos quanto você quiser.

Ou, no meu caso de teste:

newd ./dir[123]/samefile ; pwd

OUTPUT

/home/mikeserv/test/dir3
    
por 29.07.2014 / 11:46
1

Para mais portabilidade, você pode usar perl :

$ perl -MList::Util=reduce -le '
    BEGIN { $dir = "." }
    opendir DIR,$dir;
    print shift @{(reduce {$a->[1] > $b->[1] ? $a : $b}
                   map {[$_,(stat($_))[9]]}
                   grep { -d and !/^..?$/ }
                   readdir DIR)}
'
.Skype

Altere $dir para qualquer diretório que você deseja pesquisar.

Como funciona

  • readdir lista de retorno de todos os arquivos e diretório no manipulador de diretório aberto por opendir
  • grep { -d and !/^..?$/ } : obtemos todos os diretórios, pular o diretório . e .. .
  • map {[$_,(stat($_))[9]]} : cria uma matriz, seu elemento é uma referência de matriz com dois elementos:
    • primeiro é o nome do diretório
    • O segundo é o horário da modificação
  • reduce {$a->[1] > $b->[1] ? $a : $b : como uma função max, comparamos cada elemento na matriz pelo segundo elemento, que é o tempo modificado.
  • @{...} faz referência à matriz, shift obtém o primeiro elemento, que é o nome do diretório.
por 29.07.2014 / 12:15
0

Resposta curta: veja as opções man find e 'tempo'. Isso localizará o (s) arquivo (s) e, em seguida, usará a opção -printf para exibir o caminho do (s) arquivo (s), que poderá então ser usado para cd <path>

Uma maneira de usar find e extrair DIR do último arquivo acessado (nas últimas 24h) no diretório atual e seus subdiretórios
lastAccDir="$(find 2>/dev/null . -type f -atime 1 -printf "%a~%h\n" | sort -r | head -n 1 | cut -d~ -f2)"

ou o mesmo com continuação de linha (mais legível)

lastAccDir="$(
find 2>/dev/null . -type f \ -atime 1 -printf "%a~%h\n" \
 | sort -r \
 | head -n 1 \
 | cut -d~ -f2
)"

Observe que isso PODE resultar em um resultado vazio devido a -atime 1 (últimas 24h)

test ! -z "$lastAccDir" && cd "$lastAccDir"
em seguida, verifica o resultado não vazio e move-se para o dir, se não estiver vazio.

    
por 29.07.2014 / 10:40