Сценарий Bash/DOS/PowerShell для отображения самых последних версий файлов?

У нас есть список (скажем, 50) отчетов, которые сбрасываются в разные папки в зависимости от определенных условий. Все отчеты имеют стандартные имена, например. Д099К.ЛИС, Д18А0.ЛИС и т.д.

Иногда отчет может находиться в пяти разных местах, и мне нужно создать список всех местоположений самой последней версии каждого отчета.

Я могу легко сделать это, используя код или перенаправляя вывод «dir» или «ls» в текстовый файл, а затем манипулируя им в Excel, но я бы предпочел более простое (надеюсь, однострочное) решение с использованием DOS, bash, или PowerShell.

Лучшее, что я придумал до сих пор в PowerShell (я сделал что-то подобное, используя bash):

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

Это будет рекурсивно перечислять все файлы с расширением *.lis, затем сортировать их по имени (по возрастанию) и дате (по убыванию), а затем отображать каталог, имя и дату.

Это дает такой вывод:

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

Что мне, очевидно, нужно сделать сейчас, так это удалить файлы, которые не являются самыми последними версиями, чтобы вывод выглядел так (пока не слишком беспокоюсь о форматировании):

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

У кого-нибудь есть идеи?

[править] Несколько хороших идей и ответов на этот вопрос. К сожалению, я не могу пометить все как принятые, но (отредактированный) ответ EBGreen работал без изменений. Я буду добавлять сюда рабочие решения по мере их проверки.

удар:

 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

person ilitirit    schedule 06.02.2009    source источник


Ответы (8)


В bash вы можете передавать свои ответы через uniq. Я не уверен в точной структуре результатов вашего bash 1-liner, но правильные аргументы для -w N и -s N должны это сделать.

person Nick Fortescue    schedule 06.02.2009
comment
Сработало, спасибо: ls -lR --time-style=long-iso | awk 'BEGIN{OFS=\t}{print $5,$6,$7,$8}' | grep .ЛИС | сортировать -k4 -k2r -k3r | уникальный -f3 - person ilitirit; 06.02.2009
comment
прохладно. Вы, вероятно, могли бы сделать все это в awk (у него есть ассоциативные массивы), но то, что вы только что прокомментировали, так же читабельно. - person Nick Fortescue; 06.02.2009

Еще одна альтернатива в PowerShell, более «скриптовая», например:

ls -r . *.lis | sort LastWriteTime | %{$f=@{}} {$f[$_.Name]=$_} {$f.Values} | ft Directory,Name,LastWriteTime
  1. получить файлы рекурсивно
  2. отсортировать их по возрастанию по времени последней записи
  3. инициализировать хэш-карту (ассоциативный массив)
  4. для каждого файла назначьте его, используя имя в качестве ключа - более поздние записи перезапишут предыдущие
  5. получить значения хэш-карты (исключая ключи)
  6. форматировать как таблицу

Обратите внимание, что объекты FileInfo сохраняются во всем конвейере. Вы по-прежнему можете получить доступ к любому свойству/методу объектов или отформатировать их любым удобным для вас способом.

person Community    schedule 05.03.2009

Проблема, кажется, заключается в том, чтобы найти уникальный на основе определенного поля. awk можно использовать для решения этой проблемы. Видел эту запись в блоге, которая один подход. Например, в bash можно сделать:

найти . -name "*.lis" -print | xargs ls -tr | awk -F/ '!x[$NF]++'

person amit    schedule 06.02.2009
comment
Мне проще использовать ls вместо потоковой передачи результатов поиска из-за того, как упорядочены данные. Я добавил ваше предложение использовать awk в качестве возможного решения. - person ilitirit; 06.02.2009

PowerShell:

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

Объяснение:

  1. получить файлы рекурсивно
  2. сортировать файлы по убыванию LastWriteTime
  3. сортировать файлы по Имени, выбирая уникальные файлы (только первые).
  4. отформатируйте полученные объекты FileInfo в виде таблицы с каталогом, именем и временем

Альтернатива, которая не полагается на стабильность sort:

ls -r . *.lis | sort -desc LastWriteTime | group Name | %{$_.Group[0]} | ft Directory,Name,LastWriteTime
  1. получить файлы рекурсивно
  2. сортировать файлы по убыванию LastWriteTime
  3. сгруппировать файлы по имени
  4. для каждой группы выберите первый (индекс ноль) элемент группы
  5. отформатируйте полученные объекты FileInfo в виде таблицы с каталогом, именем и временем
person Community    schedule 04.03.2009
comment
Это не работает sort -u Имя курортирует данные. Он не соблюдает исходную сортировку по дате. Вот почему я использовал sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} - person ilitirit; 05.03.2009
comment
Ах, но сортировка стабильна, т.е. если ключи сортировки равны, она сохраняет их первоначальный порядок. Однако я должен признать, что это эмпирически, и я не смог проверить это из документов. Я отредактировал и добавил альтернативу. - person ; 05.03.2009
comment
Я тестировал оригинал, и он не работает, к сожалению. Через некоторое время попробую вашу вторую версию. - person ilitirit; 05.03.2009
comment
По крайней мере, в одном из примеров в официальном документе упоминается, что group является стабильной (она сортирует перед группировкой). - person ; 05.03.2009

Вы можете использовать перл? Что-то типа:

ваша команда | perl 'while (‹STDIN›) { ($dir,$name,$date) = split; $hash{$name} = ($dir,$date);} foreach (keys %hash) { print "$hash{$}[0] $ $hash{$_}[1] \п"; }'

Это может быть неправильно в деталях (прошло слишком много времени с тех пор, как я использовал perl в гневе), но основная идея заключалась в том, чтобы сохранить хэш результатов, привязанных к имени файла, и всегда перезаписывать предыдущую запись при встрече с новой записью. Таким образом, пока порядок входящих строк правильный, вы получите только те файлы, к которым недавно прикасались.

person AndyB    schedule 06.02.2009

лс-АРФлрт | awk '{print $6,$7,$8}'|grep 2010|sort -n

Искал аналог. Вышеизложенное помогло мне получить список, который я искал в bash. grep необязателен (конечно). \Спасибо

person Fregus    schedule 15.07.2010

$f = ls -r -fi *.lis | имя сортировки,lastWriteTime -desc

# Remove -whatIf to delete the files

$f[1..$f.длина] | Remove-Item -whatIf

person Shay Levy    schedule 07.02.2009
comment
Это просто перечисляет все файлы (и затем удаляет их). Я не хочу видеть все файлы, только самые последние версии. - person ilitirit; 05.03.2009

person    schedule
comment
Эпическая труба! Я никогда не использовал хеш-таблицы типа @{Name;Expression} в сортировке. - person Peter Seale; 07.02.2009