Игнорировать знак процента в пакетном файле

У меня есть пакетный файл, который перемещает файлы из одной папки в другую. Пакетный файл генерируется другим процессом.

Некоторые из файлов, которые мне нужно переместить, содержат в них строку "%20":

move /y "\\myserver\myfolder\file%20name.txt" "\\myserver\otherfolder"

Это не удается, поскольку он пытается найти файл с именем:

\\myserver\myfolder\file0name.txt

Можно ли игнорировать %? Я не могу изменить созданный файл, чтобы избежать этого, например, путем удвоения процентных знаков (%%), экранирования с помощью / или ^ (каретки) и т.д.

Ответ 1

Вы можете использовать каретку (^) чтобы избежать знака процента.

Причина %2 исчезает, так как командный файл заменяет второй переданный аргумент, и у вас, похоже, нет второго аргумента. Один из способов обойти это - попробовать на самом деле foo.bat ^%1 ^%2..., чтобы при встрече %2 в команде он был заменен буквальным %2.

Ответ 2

В этом случае вам нужно использовать %%. Обычно используется ^ (карет), но для знаков % вам нужно удвоить.

В случае %%1 или %%i или echo.%%~dp1, потому что % указывает ввод либо из команды, либо из переменной (когда она окружена %; %variable%)

Чтобы выполнить то, что вам нужно:

move /y "\\myserver\myfolder\file%%20name.txt" "\\myserver\otherfolder"

Надеюсь, это поможет!

Ответ 3

В пакетных файлах знак процента может быть "экранирован" с помощью знака с двойным процентом (%%). Таким образом, в командной строке будет использоваться один знак процента. от http://www.robvanderwoude.com/escapechars.php

Ответ 4

Заголовок вопроса очень общий, что неизбежно привлекает многих читателей, ищущих общее решение.

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

Если мы сосредоточимся на общем вопросе:

  • К сожалению, интерпретатор команд Windows cmd.exe работает по-разному в зависимости от того, указана ли строка в командной строке и внутри пакетного файла:

    • Насколько мне известно, синтаксис не содержит синтаксиса % -escaping, который будет работать как в командной строке, так и в пакетных файлах.
  • Внутри пакетного файла:

    • Используйте %% для создания литерала %, внутри строки с двойными кавычками или; например.:
      echo %%USERNAME%% приводит к буквальному %USERNAME%, а не к значению переменной USERNAME.
  • В командной строке (интерактивная командная строка в окне консоли, которая по-прежнему ошибочно называется "подсказкой DOS" ) и при вызове команды оболочки из другой программы strong > (например, используя os.system() в Python):

    • Вы не можете напрямую скрыться % в командной строке, но вы можете решить проблему:
    • Внутри неуказанной строки вы можете использовать %^ вместо открытия % ссылки на переменные, чтобы эффективно подавлять ее расширение; например.:
      echo %^USERNAME% приводит к буквальному %USERNAME%, а не к значению переменной USERNAME.
      Технически вы можете поместить ^ в любом месте имени переменной, если оно не находится рядом с другим ^, но я предлагаю принять это соглашение.

      • Обратите внимание, что этот подход не работает в строках с двойными кавычками, где ^ не имеет особого значения и сохраняется как-есть.
      • Совет шапки jeb. Обратите внимание, как ^, который обычно является escape-символом в некотируемом строки, здесь не используется (^ может выходить только символы, отличные от %); вместо этого он используется для "разрушения" имени переменной для предотвращения расширения; в деталях это работает следующим образом:

        • ^ ускользает от самого следующего символа, нужно ли экранировать этот символ или нет. Чистый эффект заключается в том, что такие экземпляры ^ в конечном итоге удаляются из некотируемых строк.

        • Однако в отношении синтаксического анализа ^ эффективно изменяет имя переменной, чтобы включить ^, а в командной строке ссылка на undefined или пустую переменную сохраняется как (в отличие от внутри пакетных файлов, где он расширяется до пустой строки).
          В нашем примере %^USERNAME% интерпретатор ищет переменную с именем ^USERNAME, которая обычно не существует, поэтому ссылка на переменную сохраняется как есть, что в сочетании с удалением ^ приводит к литералу %USERNAME%.

        • Незначительная оговорка: ^ на самом деле является юридическим символом в именах переменных (см. пример jeb в комментариях); если имя переменной начинается с ^, просто поместите "подрывную" ^ в другое место в имени переменной, если она не находится непосредственно рядом с другим ^ (так как это приведет к появлению ^ результирующая строка).
          Если ваша переменная имеет имя, например ^b^, вам не повезло.
    • Обратите внимание, что экземпляры %, которые не являются частью того, что выглядит как ссылка на переменную, рассматриваются как литералы в командной строке, независимо от того, являются ли они частью строки без кавычек или с двойными кавычками; например, echo 100% дает 100%, а echo "100%" дает "100%".
      Как указано, трюк "^ disrupter" не работает должным образом в строках с двойными кавычками, поскольку сохраняется ^.

Ответ 5

Я думаю, что у меня есть частичное решение. Если вы только хотите перенести файлы со строкой "%20" в их имени и не ищете более широкое решение, вы можете сделать второй командный файл первым, а %%2 - вторым параметром. Таким образом, когда ваша программа пытается получить второй параметр, когда он попадает в% 2 в текстовое имя, он заменит% 2 экранированным% 2, оставив имя файла без изменений.

Надеюсь, что это сработает!