Вдохновленный этой подобной записью, которая включает в себя поиск набора бит, я предлагаю следующее:
unsigned GetLowestBitPos(unsigned value)
{
double d = value ^ (value - !!value);
return (((int*)&d)[1]>>20)-1023;
}
Плюсы:
нет циклов Нет разветвлений в постоянном времени обрабатывает значение = 0, возвращая результат в противном случае, только две строки кодаМинусы:
no loops предполагает, что double является вещественным * Обновление IEEE 754. Как отмечено в комментариях, объединение является более чистой реализацией (по крайней мере, для C) и будет выглядеть так:
unsigned GetLowestBitPos(unsigned value)
{
union {
int i[2];
double d;
} temp = { .d = value ^ (value - !!value) };
return (temp.i[1] >> 20) - 1023;
}
Предполагается, что 32-битные ints с минимально-ориентированным хранилищем для всех (думаю, процессоры x86).
Вы можете найти более новый из двух файлов с одной строкой пакетного скрипта. Просто перечислите файлы в порядке дат, самые старые сначала, а это означает, что последним указанным файлом должен быть новый файл. Итак, если вы каждый раз сохраняете имя файла, последнее имя, помещенное в вашу переменную, будет самым новым файлом.
Для примера:
SET FILE1 = foo.txt SET FILE2 = bar.txt FOR / F %% i IN ('DIR / B / O: D% FILE1%% FILE2%') DO SET NEWEST = %% i ECHO% NEWEST% (возможно) новее.
Это, к сожалению, не соответствует тем, что метки дат совпадают. Поэтому нам просто нужно проверить, имеют ли файлы первую и последнюю дату:
SET FILE1 = foo.txt SET FILE2 = bar.txt FOR %% i IN (% FILE1%) DO SET DATE1 = %% ~ ti FOR %% i IN (% FILE2%) DO SET DATE2 = %% ~ ti IF "% DATE1%" == "% DATE2%" ECHO Файлы имеют одинаковый возраст и amp; & amp; & amp; GOTO END FOR / F %% i IN ('DIR / B / O: D% FILE1%% FILE2%') DO SET NEWEST = %% i ECHO Новый файл% NEWEST%: END
На основе Ответ Wes Я создал обновленный скрипт. Обновления получили слишком много, чтобы добавить комментарии.
Моя версия ниже .
Использование @REM: @REM: getfiledatestr file-path envvar Результат @REM, возвращаемый в% envvar%: getfiledatestr для %% A в (% 1) do (установить getfilefolderstr = %% ~ dpA set getfilenamestr = %% ~ nxA) @REM Удаление конечной обратной косой черты, если% getfilefolderstr: ~ -1% == \ set getfilefolderstr =% getfilefolderstr: ~ 0, -1% @REM очистить его для случая, когда команда forfiles не работает set getfiledatestr = for / f "delims =" %% i in ('"forfiles / p" "% getfilefolderstr%" "/ m" "% getfilenamestr%" "/ c" cmd / c echo @fdate @ftime ""') do set getfiledatestr = %% i @REM старый код: для %% f in (% 1) установить set getfiledatestr = %% ~ tf установить% 2 = @REM считать отсутствующие файлы как самые старые файлы, если «% getfiledatestr%» equ «" set% 2 = "" @REM В настоящее время поддерживаемые разделители разделов даты: / :. и пространство. Возможно, вам придется добавить дополнительные разделители в следующую строку, если ваш формат даты также содержит альтернативные разделители. Если вы этого не сделаете, то разобранные даты будут полностью произвольно структурированы, а сравнения - неправильными. for / f "tokens = 1,2,3,4,5,6 delims = / :." %% a in ("% getfiledatestr%") do (@REM для MM / DD / YYYY HH: MM: SS AMPM использовать вызов: appendpadded% 2 %% c %% b %% a %% g %% d %% e %% f @REM для DD / MM / YYYY HH: MM: SS AMPM использовать вызов: appendpadded% 2 %% c %% b %% a %% g %% d %% e %% f @REM для YYYY / DD / MM HH: MM: SS AMPM использовать вызов: appendpadded% 2 %% a %% b %% c %% g %% d %% e %% f call: appendpadded% 2 %% c %% b %% a %% g %% d %% e %% f) @goto: eof @REM Принимает env var в качестве первого параметра @REM и значения, которые будут добавлены в качестве остальных параметров, @REM правое заполнение всех значений с ведущими 0 до 4 мест: appendpadded set temp_value = 000% 2 call: expand set% 1 = %%% 1 %%%% temp_value: ~ -4 %% shift / 2, если «% 2» neq »« goto appendpadded set temp_value = @REM cmd не может сравнивать целые числа, превышающие 1 + 31 бит, поэтому вместо этого преобразуйте их в цитированные числовые строки. Текущая реализация генерирует числовые строки намного дольше, чем 31-битные целые числа. call: expand set% 1 = "%%% 1 %%%" @goto: eof @REM заставляет все переменные полностью развернуться: expand% * @goto: eof
серьезно, вы должны начать изучать что-то еще. Это не шутка. DOS (cmd.exe) серьезно не имеет возможности манипулирования датами и многих других недостатков. Ниже приведена следующая лучшая альтернатива, предусмотренная, помимо DOS, vbscript
Установить objFS = CreateObject ("Scripting.FileSystemObject") Установить objArgs = WScript.Arguments strFile1 = objArgs (0) strFile2 = objArgs (1 ) Установить objFile1 = objFS.GetFile (strFile1) Установить objFile2 = objFS.GetFile (strFile2) Если objFile1.DateLastModified & lt; objFile2.DateLastModified Затем WScript.Echo «File1:» & amp; strFile1 & amp; »старше, чем« & amp; strFile2 Else WScript.Echo »File1:« & amp; strFile1 & amp; »новее, чем« & amp; strFile2 End If
[ ! d5]запустите его в командной строке
C: \ test & gt; dir Громкость на диске C не имеет метки. Объемный серийный номер 08AC-4F03 Справочник C: \ test 11/06/2009 07:40 PM & lt; DIR & gt; , 11/06/2009 07:40 PM & lt; DIR & gt; .. 11/06/2009 06:26 PM 135 file 11/02/2009 04:31 PM 4,516 m.txt C: \ test & gt; cscript / nologo test.vbs файл m.txt Файл1: файл новее, чем m.txt
Конечно, в новых версиях окон вы можете попробовать Powershell ...
Для конкретной ситуации, когда вы хотите сделать что-то в стиле Makefile, перезаписывая файл назначения на основе исходного файла, только если исходный файл является более новым, я придумал этот отвратительный, но простой метод. Это только вариант, если вы никоим образом не беспокоитесь о существующем содержимом целевого файла, который старше исходного файла.
для / f "delims =" %% r in ('xcopy / D / Y / f / e "% inputdir% \% source_filename%" "% outputdir% \% dest_filename%"') do (IF "%% r" EQU "1 Файл скопирован"% build_command %!% inputdir% \% source_filename% ""% outputdir% \% dest_filename% ")
Что это такое, xcopy
только перезаписывает файл назначения, если исходный файл более новый. Если оно не новее, %% r «Скопировано 0 файлов», поэтому условная команда не выполняется, а целевой файл никогда не перезаписывается. Если он новее, %% r «Скопирован 1 файл (ы)», поэтому ваш файл назначения вкратце является копией исходного файла, затем выполняется команда сборки, заменяя его новой версией того,
Возможно, я должен был просто написать скрипт perl.
(Примечание: вы также можете xcopy
обрабатывать ситуацию, в которой место назначения файл изначально не существует, поместив звездочку в конец имени файла назначения, если вы этого не сделаете, тогда xcopy
не уверен, является ли назначение именем файла или папки, и там не имеет значения по умолчанию для ответа на имя файла.)
xcopy / DYLR src & quot; dst * & quot; | findstr / BC: "0" & gt; nul & amp; & amp; @echo dst новее
, это не перезаписывает dst
, просто проверяет, существует ли оно и новее. Да, необходима звездочка
– robert4
17 September 2015 в 15:37
Вот более простое решение. Объединив части даты как одну строку от наиболее значимого до наименее значимого, мы можем просто провести сравнение строк по результату.
Другими словами, сравнение значений YYYYMMDDAMPMHHMM даст желаемый результат без необходимости индивидуально сравнить каждый сегмент даты. Это значение получается путем конкатенации различных частей строки даты, извлеченных второй командой FOR.
call: getfiledatestr path \ file1.txt file1time call: getfiledatestr path \ file2.txt file2time if % file1time% equ% file2time% (echo path \ file1.txt - это тот же возраст, что и путь \ file2.txt с точностью до минуты) else if% file1time% lss% file2time% (echo path \ file1.txt старше пути \ file2.txt) else (echo path \ file1.txt новее, чем путь \ file2.txt) goto: eof @REM use: @REM: getfiledatestr file-path envvar @REM результат возвращается в% envvar%: getfiledatestr для %% f in (% 1) do set getfiledatestr = %% ~ tf @REM для MM / DD / YYYY HH: использование MM AMPM: appendpadded% 2 %% c %% b %% a %% f %% d %% e @ REM для DD / MM / YYYY HH: использование MM AMPM: appendpadded% 2 %% c %% b %% a %% f %% d %% e @REM для YYYY / DD / MM HH: использование MM AMPM: appendpadded% 2 %% a %% b %% c %% f %% d %% e set% 2 = for / f "tokens = 1,2,3,4,5,6 delims = /:" %% a in ("% getfiledatestr%") do (call: appendpadded% 2 %% c %% b %% a %% f %% d %% e) @goto: eof @REM Принимает env var в качестве первого параметра @REM и значения, добавляемые в качестве остальных параметров, @REM справа заполняет все значения с ведущими 0 до 4-х мест: appendpadded set temp_value = 000% 2 call: expand set% 1 = %%% 1 %%%% temp_value: ~ -4 %% shift / 2, если "% 2" neq "" goto appendpadded set temp_value = @goto: eof @REM заставляет все переменные полностью расширяться: expand% * @goto: eof
@ REM В настоящее время поддерживаемые разделители разделов даты: / :. и пространство. Возможно, вам придется добавить дополнительные разделители в следующую строку, если ваш формат даты также содержит альтернативные разделители. Если вы этого не сделаете, то разобранные даты будут полностью произвольно структурированы, а сравнения неверны.
для / f "токенов = 1,2,3,4,5,6 delims = / :. & Quot; %% a in ("% getfiledatestr%") делают (
– Roland Pihlakas
2 March 2015 в 19:05
set temp_value =
@ REM cmd не может сравнивать целые числа больше 1 + 31 бит, поэтому вместо этого преобразуйте их в строки. Текущая реализация генерирует числовые строки намного дольше, чем 31-битные целые числа.
call: expand set% 1 = "%%% 1 %%%"
@ goto: eof
– Roland Pihlakas
2 March 2015 в 19:06
if & quot;% getfiledatestr% & quot; equ "& quot; установите% 2 = "
до @ REM В настоящее время поддерживаются разделители разделов дат
... для / f" токенов = 1,2,3,4,5, 6 delims = / :. & Quot; %% a in ("% getfiledatestr%") делают (
– Roland Pihlakas
3 March 2015 в 22:50
('DIR / B / O: D% FILE1%% FILE2%')
? Я действительно не понимаю эту линию. – user15964 14 May 2015 в 12:01DIR% FILE1%% FILE2%
делает список каталогов, ищущих два файла, и поэтому должен всегда возвращать два файла. Добавление/ O: D
помещает их в порядок дат, а/ B
делает вывод "bare" поэтому это только имена файлов, а не размер файла и т. д. – Dave Webb 14 May 2015 в 12:40