Показать полную графическую версию : [решено] forfiles с переменной @path для папок с пробелом в названии.
NuclearBox
02-09-2021, 00:59
Здравствуйте.
Есть простой код переноса файлов PDF старше 30 дней в подпапку OLD текущей папки.
@echo off
chcp 1251 >nul
MD "%~dp0old"
forfiles /P "%~dp0" /D -30 /M *.pdf /C "cmd /c move @path %~dp0old\"
Подскажите, пожалуйста, в чем ошибка. Код не работает для папок, имеющих пробел в названии.
В указанном виде возвращает ошибку Неправильный параметр или аргумент - '@path'.
А если исключить из кода /P "%~dp0" , возвращает ошибку в синтаксисе команды для каждого файла.
Как исправить?
А если исключить из кода /P "%~dp0" , возвращает ошибку в синтаксисе команды для каждого файла.
Попробуйте так:
Добавьте описание переменной:
set cpath=""%~dp0old\
и измените строку на такую:
forfiles /D -30 /M *.pdf /C "cmd /c move @path %cpath%"
Всегда делай присваивание, как показал NickM. Только я делаю без заверш.слэша и через if всегда :
set "cpath=%~dp0old"
if not exist "%cpath%" md "%cpath%"
NuclearBox
02-09-2021, 11:18
NickM, wasp14, спасибо, но результат тот же - пишет "Ошибка в синтаксисе команды." при перемещении каждого файла.
а вы будьте хитрее
@echo off
chcp 1251 >nul
set "OLD=%~dp0old"
if not exist "%OLD%" md "%OLD%"
for /f "delims=" %%a in ('forfiles /p "%~dp0" /s /d -30 /m "*.pdf" /c "cmd /c echo @path"') do move "%%a" "%OLD%"
pause
NuclearBox
02-09-2021, 12:07
alpap, спасибо за совет и помощь. Но... и этот вариант не идет.
"ОШИБКА: Неправильный параметр или аргумент - '@path'."
NuclearBox,
@echo off
chcp 1251 >nul
set cpath=0x22%~dp0old\0x22
set "cpath=%cpath: =0x20%"
set ccmd="cmd /c move @path %cpath%"
set cdir="%~dp0old"
if not exist %cdir% md %cdir%
forfiles /d -30 /m *.pdf /c %ccmd%
"ОШИБКА: Неправильный параметр или аргумент - '@path'." »
а, это из-за %~dp0 под forfiles, так она не будет работать, не заметил сразу поставил как у вас в коде, а надо вот так:
@echo off
chcp 1251 >nul
set "OLD=%~dp0old"
if not exist "%OLD%" md "%OLD%"
for /f "delims=" %%a in ('forfiles /p "." /m "*.pdf" /d -30 /c "cmd /c echo @path"') do move %%a "%OLD%"
pause
NuclearBox
02-09-2021, 13:32
alpap, большое вам спасибо! Да, теперь понятно где была ошибка, и теперь работает.
NickM, большое спасибо, интересная рабочая заковыристая конструкция.
Что такое 0x22 , какой принцип? - просветите, пожалуйста.
Замена спец.символов на коды.
А так да, наверное это не оч.красивая конструкция.
forfiles /?
/C <команда> Команда, которая выполняется для каждого файла.
Строки команд необходимо заключать в прямые
кавычки.
Команда по умолчанию "cmd /c echo @file".
Следующие переменные могут использоваться
в строке команды:
@file - возвращает имя файла.
@fname - возвращает имя файла без
расширения.
@ext - возвращает только расширение имени
файла.
@path - возвращает полный путь к файлу.
@relpath - возвращает относительный путь к
файлу.
@isdir - возвращает значение "TRUE", если типом
файла является папка, и "FALSE" для файлов.
@fsize - возвращает размер файла
в байтах.
@fdate - возвращает дату последнего изменения
файла.
@ftime - возвращает время последнего изменения
файла.
Для включения специальных символов в строку команды
следует использовать шестнадцатеричный код символа
в формате 0xHH (например, 0x09 для табуляции).
Перед внутренними командами CMD.exe необходимо ставить
"cmd /c".
Поменяй сразу путь, чтоб forfiles без указания папки заработал и сё ↓
chcp 1251 >nul
rem поменяй путь чтоб forfiles без указания папки заработал и сё
cd /d "%~dp0"
set "OLD=%~dp0old"
if not exist "%OLD%" md "%OLD%"
rem и тогда проще для понимания и записи будет команда, безо всяких долгих путей, просто old и всё.
forfiles /m *.pdf /d -30 /c "cmd /c move @path old && echo @path"
pause
exit
NuclearBox
02-09-2021, 14:00
wasp14, и тебе спасибо, вариант, супер.
Всем спасибо за помощь и знания!
wasp14, в Вашем случае код сработает только если old является поддиректорией, верно?
rem поменяй путь чтоб forfiles без указания папки заработал и сё
cd /d "%~dp0" »
Не «сё». Во-первых, это вредно вообще в принципе — наглухо менять текущий каталог на каталог, где находится пакетный файл. Во-вторых, данный код «обломится» при попытке выполнить его на сетевом ресурсе.
NickM, из справки forfiles:
Параметры:
/P <путь> Путь, с которого начинается поиск. По умолчанию используется текущая рабочая папка (.)
Просто скинуть на forfiles определение где работать и где искать old . Уж он-то точно не промажет.
это вредно вообще в принципе — наглухо менять текущий каталог на каталог, где находится пакетный файл. »
какая-то херня, если чесно :dont-know А что, лучше заводить выполнение файла в %SYSTEMROOT% или %USERPROFILE% ??? Всегда меняю текущую дир-у "на_туда_где_собираюсь_крутить_cmd\bat".
данный код «обломится» при попытке выполнить его на сетевом ресурсе. »
за это ниччё не знаю. не пробовал. может и так.
какая-то херня, если чесно »
да ладно
если в команде удаление, а путь покорежился - кодировка, спецсимволы ...? - мало ли, то снос всего что рядом молча без вопросов частое явление, но неприятное.
alpap, и-мен-но, по этому и нужно менять рабочую дир-у на путь к батнику. А сам батнег, лежит в созданном для него temp-e , где и упражняемся на временных файлах. temp всегда "предельно упорот", с кириллицей и пробелами, для\шобы не попасть.
Отлаженный таким способом варик скрипта, копируем в папку откуда будем жЭчь... и обычно всё хорошо.(у меня Тотал, потому менять дир-ы и копировать 'из-в' оч.просто)
Вам достаточно известно, насколько глюкав и "просто_глупый", этот язык. Здесь много неочевидных условностей. И если можно часть неопределённостей сбросить на саму "тулзу"(forfiles или dir), то это нужно делать КМК .
cd \d мой лучший друг :)
А что, лучше заводить выполнение файла в %SYSTEMROOT% или %USERPROFILE% ??? Всегда меняю текущую дир-у "на_туда_где_собираюсь_крутить_cmd\bat". »
Для того, чтобы не пользовать порочную логику в стиле «скопировал пакетный файл в каталог, содержимое которого нужно обработать, и запустил его там» — надо пользовать аргументы пакетного файла: пакетный файл лежит в одном и том же месте, каталог для обработки передаётся ему в виде параметра (в стиле Проводника — перетащить папку на имя пакетного файла).
за это ниччё не знаю. не пробовал. может и так. »
Урок bat-аники (https://rsdn.org/article/winshell/batanyca.xml):
ПРЕДУПРЕЖДЕНИЕ
Опасайтесь бездумного применения команды cd %~dp0 без проверки результата выполнения. Теоретически, эта команда должна сменить текущий каталог на каталог, в котором расположен командный файл. Как правило, это работает. Однако возможны неожиданности. Однажды был написан простой командный сценарий, задача которого была просто удалить все каталоги рядом с собой. В «свою» директорию он переходил как раз через cd %~dp0. Все было проверено на локальной машине – работало замечательно. После этого сценарий был помещен на файл-сервер, где ему и полагалось быть. Я зашел с помощью Far в сетевой каталог, и для контрольной проверки решил запустить файл еще раз. Дальнейшее словно в тумане. cmd.exe правильно определил местонахождение bat-файла: \\servername\sharename\directory. Однако при попытке сделать туда cd, он сказал, что UNC-пути в качестве текущих каталогов не поддерживаются и лучше он сменит текущий каталог на C:\WINDOWS… Это было действительно мудрое решение… Часть сценария, отвечавшая за удаление всех каталогов, сработала отлично – хорошо, что я успел вовремя остановить это безумие.
В тот день я узнал, что такое System Restore…
В принципе, можно разрешить использование UNC-путей в качестве текущего каталога (в реестре):
[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"DisableUNCCheck":REG_DWORD
(применительно только к NT4/2k/XP/2003/Vista/2008 и cmd.exe)
CMD.EXE по умолчанию не поддерживает UNC-пути. Если Far попытаться
выполнить команду командного процессора, в случае, если текущий путь -
UNC, то в консоль выводится информация:
"Указанный путь был использован при запуске CMD.EXE в качестве текущей
папки. CMD.EXE не поддерживает пути UNC. По умолчанию выбрана системная
папка Windows. Ошибка в синтаксисе команды."
CMD.EXE был запущен с указанием '\\server\share' в качестве текущего
каталога. Пути UNC не поддерживаются. По умолчанию выбран каталог
Windows.
"CMD.EXE was started with the above path as the current directory. UNC
paths are not supported. Defaulting to Windows directory."
(выводимая информация может отличаться в NT4/W2k/XP/2003/Vista/2008)
Параметр "DisableUNCCheck" позволяет решить эту проблему. Значение
параметра может быть одним из следующих:
0 - выводить предупреждающее сообщение и устанавливать текущий путь
равный системной папке Windows.
1 - не выводить предупреждающее сообщение и пытаться выставить текущий
путь равный UNC пути.
По умолчанию в Windows параметр равен 0.
Рекомендуемое значение 1.
Подробнее: http://www.winguides.com/registry/display.php/1247/
или в статье Microsoft - Q156276
но это надо проделывать предварительно.
по этому и нужно менять рабочую дир-у на путь к батнику. »
Вот это я и называю порочной логикой. Не нужно. Мухи отдельно, котлеты отдельно должны быть.
cd \d мой лучший друг »
Тогда уж хотя бы:
pushd "…" && (
…
…
popd
)
чтобы не было мучительно больно.
.(у меня Тотал, потому менять дир-ы и копировать 'из-в' оч.просто) »
Тем более непонятно, почему Вы в Total Commander'е не пользуете правильный подход:
https://i.imgur.com/OTKiSAG.png
Ctrl-F, Tab:
https://i.imgur.com/lKLeN8R.png
Enter.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.