Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] forfiles с переменной @path для папок с пробелом в названии. (http://forum.oszone.net/showthread.php?t=349519)

NuclearBox 02-09-2021 00:59 2965613

forfiles с переменной @path для папок с пробелом в названии.
 
Здравствуйте.
Есть простой код переноса файлов 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" , возвращает ошибку в синтаксисе команды для каждого файла.
Как исправить?

NickM 02-09-2021 06:46 2965618

Цитата:

А если исключить из кода /P "%~dp0" , возвращает ошибку в синтаксисе команды для каждого файла.
Попробуйте так:

Добавьте описание переменной:
Код:

set cpath=""%~dp0old\
и измените строку на такую:
Код:

forfiles /D -30 /M *.pdf /C "cmd /c move @path %cpath%"

wasp14 02-09-2021 08:34 2965622

Всегда делай присваивание, как показал NickM. Только я делаю без заверш.слэша и через if всегда :
Код:

set "cpath=%~dp0old"
if not exist "%cpath%" md "%cpath%"


NuclearBox 02-09-2021 11:18 2965642

NickM, wasp14, спасибо, но результат тот же - пишет "Ошибка в синтаксисе команды." при перемещении каждого файла.

alpap 02-09-2021 11:54 2965653

а вы будьте хитрее
Код:

@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 2965654

alpap, спасибо за совет и помощь. Но... и этот вариант не идет.
"ОШИБКА: Неправильный параметр или аргумент - '@path'."

NickM 02-09-2021 12:33 2965655

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%


alpap 02-09-2021 13:08 2965660

Цитата:

Цитата NuclearBox
"ОШИБКА: Неправильный параметр или аргумент - '@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 2965664

alpap, большое вам спасибо! Да, теперь понятно где была ошибка, и теперь работает.

NickM, большое спасибо, интересная рабочая заковыристая конструкция.
Что такое 0x22 , какой принцип? - просветите, пожалуйста.

NickM 02-09-2021 13:40 2965666

Замена спец.символов на коды.

А так да, наверное это не оч.красивая конструкция.

Код:

forfiles /?
Скрытый текст
Код:

    /C  <команда>      Команда, которая выполняется для каждого файла.
                        Строки команд необходимо заключать в прямые
                        кавычки.

                        Команда по умолчанию "cmd /c echo @file".

                        Следующие переменные могут использоваться
                        в строке команды:
                        @file    - возвращает имя файла.
                        @fname  - возвращает имя файла без
                                  расширения.
                        @ext    - возвращает только расширение имени
                                  файла.
                        @path    - возвращает полный путь к файлу.
                        @relpath - возвращает относительный путь к
                                  файлу.
                        @isdir  - возвращает значение "TRUE", если типом
                                  файла является папка, и "FALSE" для файлов.
                        @fsize  - возвращает размер файла
                                  в байтах.
                        @fdate  - возвращает дату последнего изменения
                                  файла.
                        @ftime  - возвращает время последнего изменения
                                  файла.

                        Для включения специальных символов в строку команды
                        следует использовать шестнадцатеричный код символа
                        в формате 0xHH (например, 0x09 для табуляции).

                        Перед внутренними командами CMD.exe необходимо ставить
                        "cmd /c".


wasp14 02-09-2021 13:43 2965667

Поменяй сразу путь, чтоб 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 2965669

wasp14, и тебе спасибо, вариант, супер.

Всем спасибо за помощь и знания!

NickM 02-09-2021 14:34 2965670

wasp14, в Вашем случае код сработает только если old является поддиректорией, верно?

Iska 02-09-2021 22:07 2965702

Цитата:

Цитата wasp14
Код:

rem поменяй путь чтоб forfiles без указания папки заработал и сё
cd /d "%~dp0"

»

Не «сё». Во-первых, это вредно вообще в принципе — наглухо менять текущий каталог на каталог, где находится пакетный файл. Во-вторых, данный код «обломится» при попытке выполнить его на сетевом ресурсе.

wasp14 04-09-2021 13:42 2965817

NickM, из справки forfiles:
Код:

Параметры:
    /P  <путь>          Путь, с которого начинается поиск. По умолчанию используется текущая рабочая папка (.)

Просто скинуть на forfiles определение где работать и где искать old . Уж он-то точно не промажет.
Цитата:

Цитата Iska
это вредно вообще в принципе — наглухо менять текущий каталог на каталог, где находится пакетный файл. »

какая-то херня, если чесно :dont-know А что, лучше заводить выполнение файла в %SYSTEMROOT% или %USERPROFILE% ??? Всегда меняю текущую дир-у "на_туда_где_собираюсь_крутить_cmd\bat".
Цитата:

Цитата Iska
данный код «обломится» при попытке выполнить его на сетевом ресурсе. »

за это ниччё не знаю. не пробовал. может и так.

alpap 04-09-2021 13:57 2965821

Цитата:

Цитата wasp14
какая-то херня, если чесно »

да ладно
если в команде удаление, а путь покорежился - кодировка, спецсимволы ...? - мало ли, то снос всего что рядом молча без вопросов частое явление, но неприятное.

wasp14 04-09-2021 14:35 2965823

alpap, и-мен-но, по этому и нужно менять рабочую дир-у на путь к батнику. А сам батнег, лежит в созданном для него temp-e , где и упражняемся на временных файлах. temp всегда "предельно упорот", с кириллицей и пробелами, для\шобы не попасть.
Отлаженный таким способом варик скрипта, копируем в папку откуда будем жЭчь... и обычно всё хорошо.(у меня Тотал, потому менять дир-ы и копировать 'из-в' оч.просто)

Вам достаточно известно, насколько глюкав и "просто_глупый", этот язык. Здесь много неочевидных условностей. И если можно часть неопределённостей сбросить на саму "тулзу"(forfiles или dir), то это нужно делать КМК .
cd \d мой лучший друг :)

Iska 04-09-2021 16:00 2965833

Цитата:

Цитата wasp14
А что, лучше заводить выполнение файла в %SYSTEMROOT% или %USERPROFILE% ??? Всегда меняю текущую дир-у "на_туда_где_собираюсь_крутить_cmd\bat". »

Для того, чтобы не пользовать порочную логику в стиле «скопировал пакетный файл в каталог, содержимое которого нужно обработать, и запустил его там» — надо пользовать аргументы пакетного файла: пакетный файл лежит в одном и том же месте, каталог для обработки передаётся ему в виде параметра (в стиле Проводника — перетащить папку на имя пакетного файла).

Цитата:

Цитата wasp14
за это ниччё не знаю. не пробовал. может и так. »

Урок bat-аники:
Цитата:

ПРЕДУПРЕЖДЕНИЕ

Опасайтесь бездумного применения команды 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


но это надо проделывать предварительно.

Цитата:

Цитата wasp14
по этому и нужно менять рабочую дир-у на путь к батнику. »

Вот это я и называю порочной логикой. Не нужно. Мухи отдельно, котлеты отдельно должны быть.

Цитата:

Цитата wasp14
cd \d мой лучший друг »

Тогда уж хотя бы:
Код:

pushd "…" && (
    …
    …
    popd
)

чтобы не было мучительно больно.

Iska 04-09-2021 16:17 2965837

Цитата:

Цитата wasp14
.(у меня Тотал, потому менять дир-ы и копировать 'из-в' оч.просто) »

Тем более непонятно, почему Вы в Total Commander'е не пользуете правильный подход:
Скрытый текст


Ctrl-F, Tab:



Enter.


Время: 16:40.

Время: 16:40.
© OSzone.net 2001-