J'ai des répertoires dont les noms sont des horodatages, donnés en millisecondes depuis le 01/01/1970:
1439715011728
1439793321429
1439879712214
.
.
Et j'ai besoin d'une sortie comme:
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
.
.
Je peux lister tous les répertoires par commande:
find ./ -type d | cut -c 3-12
Mais je ne peux pas mettre la sortie à la commande suivante: date -d @xxxxxx
et manipuler la sortie.
Comment puis-je faire ceci?
Fri Oct 2 05:35:28 47592
)Réponses:
Vous êtes sur la bonne voie (pour une solution plus simple, n'exécutant que 2 ou 3 commandes, voir ci-dessous). Vous devriez utiliser
*
au lieu de./
pour vous débarrasser du répertoire courant¹ et cela simplifie quelque peu la coupe des millisecondes, puis il suffit de diriger le résultat en GNUparallel
ouxargs
²:obtenir
et pour ajouter le décalage des secondes avant cela comme l'indique votre exemple:
ou:
obtenir:
Cependant, c'est plus simple à faire³:
ce qui vous donne à nouveau la même sortie demandée.
L'inconvénient de l'utilisation
*
est que vous êtes limité par votre ligne de commande pour son expansion, l'avantage est cependant que vous obtenez vos répertoires triés par valeur d'horodatage. Si le nombre de répertoires pose problème-mindepth 1
, mais perdez l'ordre:et insérer
sort
si besoin:¹ Cela suppose qu'il n'y a pas de sous-répertoires imbriqués, comme cela semble être le cas dans votre exemple. Vous pouvez également utiliser
./ -mindepth 1
au lieu de*
² Vous pouvez remplacer
parallel
parxargs -I{}
ici comme @hobbs et @don_crissti l'ont suggéré, c'est juste plus verbeux. ³ basé sur la réponse de Gilles pour utiliserdate
les capacités de lecture de fichiers de sla source
xargs
si vous n'en avez pasparallel
, ce que beaucoup de gens n'ont probablement pas.xargs
n'a pas la possibilité de spécifier où l'argument va commeparallel
a avec{}
.find ./ -type d | cut -c 3-12 | xargs -I{} date --d @{} +'%Y-%m-%d'
-I
option.--d
ou--da
fonctionnerait avec les versions actuelles de GNUdate
, mais il pourrait cesser de fonctionner le jourdate
introduit une--dalek
option (pour les dates dans le calendrier Dalek).J'éviterais d'exécuter plusieurs commandes par fichier dans une boucle. Puisque vous utilisez déjà GNUisms:
Qui exécute simplement deux commandes.
strftime()
est spécifique à GNU, commedate -d
.la source
Tu as déjà:
qui vous donne probablement les horodatages au format d'époque. Ajoutez maintenant une boucle while:
Notez cependant que dans certains shells, cette syntaxe obtient la boucle while dans un sous-shell, ce qui signifie que si vous essayez de définir une variable là-bas, elle ne sera pas visible une fois que vous aurez quitté la boucle. Pour résoudre ce problème, vous devez légèrement tourner les choses:
ce qui place le
find
dans le sous-shell, et conserve la boucle while dans le shell principal. Cette syntaxe (AT & Tksh
,zsh
etbash
spécifique) est nécessaire que si vous cherchez à réutiliser un résultat à l' intérieur de la boucle, cependant.la source
done <(find)
au lieu dedone < <(find)
, c'était correct pouryash
(où<(...)
est la redirection de processus, pas la substitution de processus), donc mon montage était un peu cavalier car il aurait pu être le shell pour lequel vous vouliez dire.Si vous avez une date GNU, elle peut convertir les dates lues à partir d'un fichier d'entrée. Il vous suffit de masser un peu les horodatages pour qu'il puisse les reconnaître. La syntaxe d'entrée pour un horodatage basé sur l'époque Unix est
@
suivie du nombre de secondes, qui peut contenir un point décimal.la source
date
la lecture de fichiers s. Cela donnera un àdate: invalid date ‘@’
cause de la traduction du répertoire courant (./
). Et comme vous pouvez jeter les millisecondes, vous pouvez simplifier la deuxièmesed
modification pour simplement supprimer les 3 derniers caractères. Ou supprimez tout cela et utilisezfind * -type d -printf "@%.10f" | date ...
Je le ferais périlleusement - alimenter une liste d'horodatages:
Cela produit:
Si vous souhaitez un format de sortie spécifique, vous pouvez utiliser
strftime
par exemple:Que pour transformer cela en une doublure dans votre tuyau:
Mais je suggérerais probablement plutôt d'utiliser le
File::Find
module et de faire le tout en perl à la place. Si vous donnez un exemple de votre structure de répertoires avant de le couper, je vais vous donner un exemple. Mais ce serait quelque chose comme:la source
Avec
zsh
et le strftime intégré:cela suppose que tous les noms de votre répertoire dans le répertoire actuel sont en fait des époques.
Un filtrage / traitement supplémentaire est possible à condition de clarifier la façon dont ces chiffres dans votre exemple doivent être traités (ils ressemblent plus à des époques correspondant aux dates de naissance de la princesse Leia et de Luke Skywalker ...), par exemple, rechercher récursivement des noms de répertoire qui correspondent au moins 10 chiffres et calculez la date sur la base des 10 premiers chiffres:
la source
Utilisation de GNU Parallel:
Si vous pouvez accepter \ t au lieu de l'espace:
la source
parallel
c'est écritperl
. Cela semble exagéré étant donné qu'ilperl
a unstrftime()
opérateur. J'aimeperl -MPOSIX -lpe '$_.=strftime(" %c", localtime substr $_, 2, 10)'
parallel
. IMO,parallel
est un excellent outil pour paralléliser les tâches gourmandes en ressources processeur, mais pas vraiment approprié pour ce type de tâche ici.Normalement, la commande find peut être chaînée avec n'importe quelle commande utilisant un
exec
argument.Dans votre cas, vous pouvez faire comme ceci:
la source
Utiliser Python (c'est la solution la plus lente probablement)
donne:
la source