Eu tenho diretórios cujos nomes são timestamps, dados em milissegundos desde 01-01-2009:
1439715011728
1439793321429
1439879712214
.
.
E eu preciso de uma saída como:
1442039711 Sat Sep 12 08:35:11 CEST 2015
1442134211 Sun Sep 13 10:50:11 CEST 2015
1442212521 Mon Sep 14 08:35:21 CEST 2015
.
.
Eu posso listar todos os diretórios por comando:
find ./ -type d | cut -c 3-12
Mas não posso colocar a saída no próximo comando: date -d @xxxxxx
e manipular a saída.
Como posso fazer isso?
Fri Oct 2 05:35:28 47592
)Respostas:
Você está no caminho certo (para uma solução mais simples, executando apenas 2 ou 3 comandos, veja abaixo). Você deve usar em
*
vez de./
se livrar do diretório atual¹ e isso simplifica um pouco o corte dos milissegundos, em seguida, basta canalizar o resultado no GNUparallel
ouxargs
²:para obter
e para adicionar o deslocamento dos segundos antes disso, como indica o seu exemplo:
ou:
para obter:
No entanto, é mais simples de fazer³:
que fornece a mesma saída solicitada mais uma vez.
A desvantagem do uso
*
é que você está limitado pela linha de comando para sua expansão, mas a vantagem é que você classifica seus diretórios pelo valor do carimbo de data / hora. Se o número de diretórios for um problema-mindepth 1
, use , mas perca a ordem:e insira,
sort
se necessário:¹ Isso pressupõe que não haja subdiretórios aninhados, como parece ser o caso do seu exemplo. Você também pode usar
./ -mindepth 1
em vez de*
² Você pode substituir
parallel
comxargs -I{}
aqui como @hobbs e @don_crissti sugeriu, apenas mais detalhado. ³ com base na resposta de Gilles para usardate
os recursos de leitura de arquivosfonte
xargs
se você não tiverparallel
, o que muitas pessoas provavelmente não têm.xargs
não tem a opção de especificar onde o argumento vai comoparallel
tem com{}
.find ./ -type d | cut -c 3-12 | xargs -I{} date --d @{} +'%Y-%m-%d'
-I
opção.--d
ou--da
funcionaria com as versões atuais do GNUdate
, mas poderia parar de funcionar quando o diadate
introduzir uma--dalek
opção (para datas no calendário Dalek).Eu evitaria executar vários comandos por arquivo em um loop. Como você já está usando o GNUisms:
Que apenas executa dois comandos.
strftime()
é específico do GNU, comodate -d
.fonte
Você já tem:
o que provavelmente fornece os registros de data e hora em formato de época. Agora adicione um loop while:
Observe, porém, que em alguns shells, essa sintaxe obtém o loop while em um subshell, o que significa que se você tentar definir uma variável lá, ela não ficará visível quando você sair do loop. Para consertar isso, você precisa virar um pouco as coisas:
o que coloca o
find
subshell e mantém o loop while no shell principal. Que a sintaxe (AT & Tksh
,zsh
ebash
específico) só é necessário se você estiver olhando para reutilizar um resultado de dentro do loop, no entanto.fonte
done <(find)
vez dedone < <(find)
estar corretoyash
(onde<(...)
está o redirecionamento do processo, não a substituição do processo), minha edição foi um pouco descuidada, pois poderia ter sido o shell para o qual você pretendia.Se você tiver uma data GNU, ele poderá converter as datas lidas de um arquivo de entrada. Você só precisa massagear um pouco os timestamps para que eles possam reconhecê-los. A sintaxe de entrada para um registro de data e hora com base na época do Unix é
@
seguida pelo número de segundos, que pode conter um ponto decimal.fonte
date
a leitura de arquivos s. Isso dará umadate: invalid date ‘@’
causa da tradução do diretório atual (./
). E como você pode jogar fora os milissegundos, você pode simplificar a segundased
edição para soltar apenas os últimos 3 caracteres. Ou remover tudo isso e usarfind * -type d -printf "@%.10f" | date ...
Eu faria isso perlishly - alimente uma lista de timestamps:
Isso gera:
Se você deseja um formato de saída específico, pode usar
strftime
por exemplo:Qual transformar isso em um forro no seu tubo:
Mas eu provavelmente sugeriria, em vez disso, examinar o
File::Find
módulo e fazer a coisa toda em perl. Se você der um exemplo da sua estrutura de diretórios antes de cortá-la, darei um exemplo. Mas seria algo como:fonte
Com
zsh
e o tempo de execução incorporado:isso pressupõe que todos os nomes de diretório no diretório atual sejam realmente épocas.
É possível filtrar / processar mais, desde que você esclareça como esses números no seu exemplo devem ser processados (eles se parecem mais com os tempos da época correspondentes às datas de nascimento da princesa Leia e Luke Skywalker ...). Por exemplo, procure recursivamente por nomes de diretórios que correspondam a pelo menos 10 dígitos e calcule a data com base nos 10 primeiros dígitos:
fonte
Usando o GNU Parallel:
Se você pode aceitar \ t em vez de espaço:
fonte
parallel
está escrito emperl
. Isso parece um exagero, considerando queperl
tem umstrftime()
operador. Likeperl -MPOSIX -lpe '$_.=strftime(" %c", localtime substr $_, 2, 10)'
parallel
. O IMOparallel
é uma ótima ferramenta para paralelizar tarefas intensivas da CPU, mas não é realmente apropriado para esse tipo de tarefa aqui.Normalmente, o comando find pode ser encadeado com qualquer comando usando o
exec
argumentoNo seu caso, você pode fazer assim:
fonte
Usando Python (é a solução mais lenta possível)
dá:
fonte