2009-02-06 8 views
5

Tenemos una lista de (digamos 50) informes que se vuelcan en varias carpetas dependiendo de ciertas condiciones. Todos los informes tienen nombres estándar, por ejemplo. D099C.LIS, D18A0.LIS etc.secuencia de comandos Bash/DOS/PowerShell para listar las versiones más recientes de los archivos?

A veces, un informe puede existir en hasta 5 ubicaciones diferentes, y necesito generar una lista de todas las ubicaciones de la versión más reciente de cada informe.

Lo puedo hacer fácilmente usando código, o redireccionando salida "dir" o "ls" a un archivo de texto y luego manipulándolo en Excel, pero preferiría una solución más simple (ojalá una línea) ya sea usando DOS, bash o PowerShell.

El mejor que he encontrado hasta el momento en PowerShell (que he hecho algo similar usando bash) es:

ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | select Directory, Name, lastwritetime 

que la voluntad de forma recursiva una lista de todos los archivos con la extensión * .lis, luego clasificarla por nombre (asc) y fecha (desc), y luego mostrar el directorio, nombre y fecha.

Esto le da a este tipo de salida:

C:\reports\LESE   D057A.LIS     28/01/2009 09:00:43 
C:\reports\JCSW   D057A.LIS     27/01/2009 10:50:21 
C:\reports\ALID   D075A.LIS     04/02/2009 12:34:12 
C:\reports\JCSW   D075B.LIS     05/02/2009 10:07:15 
C:\reports\ALID   D075B.LIS     30/01/2009 09:14:57 
C:\reports\BMA3   D081A.LIS     01/09/2008 14:51:36 

Lo que obviamente tendrá que hacer ahora es eliminar los archivos que no son las versiones más recientes, por lo que la salida se parece a esto (no demasiado preocupado formateo todavía):

C:\reports\LESE   D057A.LIS     28/01/2009 09:00:43 
C:\reports\JCSW   D075B.LIS     05/02/2009 10:07:15 
C:\reports\BMA3   D081A.LIS     01/09/2008 14:51:36 

¿Alguien tiene alguna idea?

[editar] Algunas buenas ideas y respuestas a esta pregunta. Desafortunadamente no puedo marcar todo como aceptado, pero la respuesta de EBGreen (editada) funcionó sin modificaciones. Agregaré soluciones de trabajo aquí mientras las verifico.

bash:

ls -lR --time-style=long-iso | awk 'BEGIN{OFS="\t"}{print $5,$6,$7,$8}' | grep ".LIS" | sort -k4 -k2r -k3r | uniq -f3 
ls -lR --time-style=long-iso | awk 'BEGIN{OFS="\t"}{print $5,$6,$7,$8}' | grep ".LIS" | sort -k4 -k2r -k3r | awk '!x[$4]++' 

PowerShell:

ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | select Directory, Name, lastwritetime | Group-Object Name | %{$_.Group | Select -first 1} 
    ls -r . *.lis | sort -desc LastWriteTime | group Name | %{$_.Group[0]} | ft Directory,Name,LastWriteTime 
    ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | unique | ft Directory,Name,LastWriteTime 

Respuesta

8
ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | select Directory, Name, lastwritetime | Group-Object Name | %{$_.Group | Select -first 1} 
+0

Eso solo da los primeros 3 en la lista. No es lo que quiero en absoluto.Necesito una lista de la versión más reciente de cada archivo. – ilitirit

+0

Aaah ... No entendí bien. Trabajaré en eso. – EBGreen

+0

Ver si eso funciona ahora. – EBGreen

2

En bash se podía tubería sus respuestas a través de uniq. No estoy seguro de la estructura exacta para los resultados de tu bash 1-liner, pero los argumentos correctos para -w N y -s N deberían hacerlo.

+0

Buena idea, lo intentaré. – ilitirit

+0

Funcionó, gracias: ls -lR --time-style = long-iso | awk 'BEGIN {OFS = "\ t"} {imprimir $ 5, $ 6, $ 7, $ 8}' | grep ".LIS" | ordenar -k4 -k2r -k3r | uniq -f3 – ilitirit

+0

genial. Probablemente puedas hacerlo todo en awk (tiene matrices asociativas) pero lo que acabas de comentar es igual de legible. –

0

¿Se puede usar perl? Algo como:

su comando | perl 'while (<STDIN>) {($ dir, $ nombre, $ fecha) = división; $ hash {$ name} = ($ dir, $ date);} foreach (keys% hash) {print "$ hash {$ } [0] $ $ hash {$ _} [1] \ n"; } '

Esto podría estar mal en los detalles (ha pasado demasiado tiempo desde que usé Perl con ira) pero la idea básica es mantener un hash de resultados en el nombre del archivo y siempre sobrescribir la entrada anterior al encontrar una nueva entrada . De esta forma, siempre que el orden de las líneas sea correcto, solo obtendrá los archivos tocados recientemente que salgan.

1

El problema parece ser encontrar único en función de un campo en particular. awk se puede usar para resolver este problema. Vi esto blog entry que tiene un enfoque. Por ejemplo, en bash se puede hacer:

buscar. -name "* .lis" -print | xargs ls -tr | awk -F/'! x [$ NF] ++'

+0

Me resulta más fácil usar ls, en lugar de transmitir los resultados de búsqueda debido a la forma en que se ordenan los datos. Sin embargo, he agregado tu sugerencia de usar awk como una posible solución. – ilitirit

-1

$ f = ls -r -fi * .lis | ordenar nombre, lastWriteTime -desc

# Eliminar -whatIf para eliminar los archivos

$ f [1 .. $ f.length] | Remove-Item -whatIf

+0

Esto simplemente enumera todos los archivos (y los elimina luego). No quiero ver todos los archivos, solo las versiones más recientes. – ilitirit

1

Powershell:

ls -r . *.lis | sort -desc LastWriteTime | sort -u Name | ft Directory,Name,LastWriteTime 

Explicación:

  1. obtener los archivos de forma recursiva
  2. ordenar los archivos que descienden por LastWriteTime
  3. ordenar los archivos por nombre, seleccionando único archivos (solo el primero).
  4. formato de las resultantes objetos FileInfo en una mesa con el directorio, nombre y la hora

alternativo que no se basa en tipo ser estable:

ls -r . *.lis | sort -desc LastWriteTime | group Name | %{$_.Group[0]} | ft Directory,Name,LastWriteTime 
  1. obtener los archivos de forma recursiva
  2. ordenar los archivos descendientes por LastWriteTime
  3. agrupar los archivos por nombre
  4. para cada grupo seleccione el primer elemento (índice cero) del grupo
  5. formato de los objetos FileInfo resultantes en una mesa con Directorio, Nombre y Tiempo
+0

Esto no funciona "ordenar -u Nombre" recurre a los datos. No respeta el tipo original por fecha. Es por eso que utilicé "sort @ {expression = {$ _. Name}}, @ {expression = {$ _. LastWriteTime}; Descending = $ true}" – ilitirit

+0

Ah, pero "sort" es estable, es decir, si las claves de clasificación son igual, conserva su orden inicial. Sin embargo, debo admitir que esto es empírico y no he podido verificarlo desde los documentos. He editado y agregado una alternativa. –

+0

He probado el original y no funciona, desafortunadamente. Voy a probar tu segunda versión en un momento. – ilitirit

2

Otra alternativa en PowerShell, más "guión" como :

ls -r . *.lis | sort LastWriteTime | %{[email protected]{}} {$f[$_.Name]=$_} {$f.Values} | ft Directory,Name,LastWriteTime 
  1. obtener los archivos de forma recursiva
  2. especie ellos ascendiendo por última vez escribir
  3. inicializar un mapa hash (matriz asociativa)
  4. para cada archivo asignarla utilizando el nombre como la clave - entradas posteriores se sobreponen a las anteriores
  5. obtener los valores de la HashMap (llaves incluidas)
  6. formato como una tabla

Nota, los objetos FileInfo se conservan a lo largo de la canalización. Aún puede acceder a cualquier propiedad/método de los objetos o formatearlos de la forma que desee.

0

ls -ARFlrt | awk '{print $ 6, $ 7, $ 8}' | grep 2010 | sort -n

Estaba buscando similares. Lo anterior me ha ayudado a obtener el listado que buscaba en bash. El grep es opcional (por supuesto). \ gracias

Cuestiones relacionadas