Пакетные файлы не могут переместить указанные файлы
forfiles /D +12/1/%2 /C "cmd /c if /I @FDATE LEQ 12/31/%2 move @file %3\Archive\12-%2 >NUL"
Предполагается, что forfiles предназначаются для всех файлов с датами последнего изменения в период с 01.12.2015 по 31.12.2015 (включая 1-е и 31-е) и перемещают их в архив. По неизвестным причинам некоторые файлы с последней измененной датой 03.12.2015 и 09.12.2015 не перемещаются. Кроме того, ВСЕ файлы с последней измененной датой с 12.12.2015 по 08.12.2015 не перемещаются.
Шаги, предпринятые для отладки: Обработано в разные месяцы: январь, февраль и т. Д., И архивирование прошло успешно. Разрешения были проверены и проверены. Вручную заархивировал неподвижные файлы. Созданные копии неподвижных файлов и до сих пор сталкиваются с теми же проблемами. Последнее, что я сделал, это заменил
if /I @FDATE LEQ 12/31/%2 move @file %3\Archive\12-%2 >NUL
с
echo @FDATE
чтобы убедиться, что ВСЕ измененные даты видны. Измененные даты для файлов, которые не были успешно перемещены и заархивированы, видны.
3 ответа
Как уже отметил @JosefZ в своем комментарии, if
не способен сравнивать значения даты.
Однако, чтобы отфильтровать файлы по определенному диапазону для даты изменения, вы можете использовать два вложенных forfiles
петли:
> nul 2>&1 forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C if 00x7840isdir==FALSE > con echo 00x7840fdate 00x7840file0x22"
развитие
Внешний цикл двух вложенных forfiles
Циклы перечисляют элементы с заданной нижней границей диапазона для дат модификации (дата указывается в формате dd-MM-yyyy
согласно (короткому) формату даты моей системы; проверить текст справки forfiles /?
чтобы узнать правильный формат для вашей системы):
forfiles /D +01-12-2015
Возвращает все элементы, измененные 1 декабря 2015 года или позднее.
Затем внутренний цикл используется для возврата только тех товаров, которые были изменены 31 декабря 2015 года или ранее. Для этого нам нужно создать командную строку, основанную на следующем:
forfiles /M * /D -31-12-2015 /C "cmd /C echo @fdate @file"
Маска после /M
должен быть установлен на @file
значение, возвращаемое внешним циклом, поэтому внутренний цикл повторяется только один раз за каждую повторение внешнего цикла; поэтому внутренний цикл просто фильтрует каждый отдельный элемент, полученный внешним, по дате его модификации. Расположение после /P
не нужно указывать, так как внешний цикл выполняет внутренний цикл (или вообще команду после /C
) уже из каталога находится текущий итеративный элемент (это также верно, если /S
Переключатель предназначен для обработки подкаталогов также).
Задача сейчас состоит в том, чтобы скрыть такие переменные, как @file
внутренней петли от внешней петли. Хитрость заключается в использовании функции подстановки шестнадцатеричного кода forfiles
; например, 0x20
будет заменен пробелом, 0x22
кавычкой, 0x40
посредством @
и 0x78
это письмо x
, Поскольку эта замена выполняется еще до замены @
переменные, мы должны заявить 00x7840
скрыть @
символ из внешнего цикла и, таким образом, чтобы избежать замены @file
Например, потому что @
станет 0x40
, так что внутренний цикл получает 0x40file
, который будет преобразован обратно в @file
а затем сразу же заменить его значение.
Так что командная строка с вложенным forfiles
петли могут выглядеть так:
forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C echo 00x7840fdate 00x7840file0x22"
Чтобы отфильтровать каталоги и вернуть только файлы, необходимо проверить @isdir
:
forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C if 00x7840isdir==FALSE echo 00x7840fdate 00x7840file0x22"
Наконец, чтобы избежать пустых строк или сообщений об ошибках, которые должны быть возвращены forfiles
, используйте перенаправление:
> nul 2>&1 forfiles /D +01-12-2015 /C "forfiles forfiles /M @file /D -31-12-2105 /C 0x22cmd /C if 00x7840isdir==FALSE > con echo 00x7840fdate 00x7840file0x22"
Посмотрите также следующие посты:
- Как вложить два
forfiles
циклы правильно (так что внутреннее тело расширяет переменные обоих уровней итерации)? - forfiles без cmd / c (это объясняет странный синтаксис
forfiles /C "forfiles forfiles"
)
Вот что я НАКОНЕЦ получил на работу:
SET Backups=C:\Users\%username%\Documents\Backups
forfiles /P %Backups%\Backups--Cisco_Smartnet /m *.xls /D -90 /C
"cmd /c move @file %Backups%\Backups--Cisco_Smartnet\Old_Backups--
3+_Months_Old
Для меня это перемещение электронных таблиц (.xls), которым исполнилось 90 дней или старше (/D -90), в папку старых резервных копий. @file - это любой файл в каталоге, который соответствует этим критериям. Переменная%backups% не важна для этой команды, она просто экономит мое время, когда я делаю много из них. Строка SET - это собственная строка. А от Forfiles до конца есть своя линия.
Я надеюсь, что это помогает, весело провести время!
Командная строка if
не способен сравнивать значения даты. Например, см. Ложные результаты в интервале дат между March 30, 2016
а также April 10, 2016
(то есть между 30.3.2016
а также 10.4.2016
с точки зрения моей локали Windows):
==> forfiles /D +30.3.2016 /C "cmd /c if @FDATE leq 10.4.2016 (echo @fdate yes @file) else ( echo @fdate NOO @file)"
31.03.2016 NOO "file36322183.txt"
12.04.2016 NOO "inputs.bat"
03.04.2016 yes "mycharmap.bat"
09.04.2016 yes "SO"
12.04.2016 NOO "ttt.txt"
==>
Переход на powershell не кажется менее громоздким, чем вложенный forfiles
:
==> forfiles /D +30.3.2016 /C "powershell -command if ('@FDATE'.ToDateTime([Globalization.CultureInfo]::CurrentCulture) -le '10.4.2016'.ToDateTime([Globalization.CultureInfo]::CurrentCulture)) { echo '@fdate yes @file'} else { echo '@fdate NOO @file'}"
31.03.2016 yes file36322183.txt
12.04.2016 NOO inputs.bat
03.04.2016 yes mycharmap.bat
09.04.2016 yes SO
12.04.2016 NOO ttt.txt
==>
Команда Powershell дает правильные результаты. Тем не менее, я бы проверить @isdir
собственность (см. SO
папка в обоих списках выше).