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

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

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

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

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

\\myserver\myfolder\file0name.txt

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

5 ответов

Решение

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

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

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

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

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

Чтобы достичь того, что вам нужно:

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

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

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

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

Как вы используете % как буквальный символ в командном файле / в командной строке?

  • Внутри командного файла всегда убегай % как %% будь то в кавычках или нет; следующие урожаи My %USERNAME% is jdoe, например:

    echo My %%USERNAME%% is %USERNAME%
    echo "My %%USERNAME%% is %USERNAME%"
    
  • В командной строке (в интерактивном режиме) - а также при использовании вызывающих оболочку функций языков сценариев - поведение принципиально отличается от поведения внутри командных файлов: технически, % невозможно избежать этого, и нет единого обходного пути, которое работает во всех ситуациях:

    • В строках без кавычек вы можете использовать ^ трюк "разрушитель имен": для простоты поместите ^ перед каждым % символ, но учтите, что хотя вы технически не спасаетесь % таким образом (подробнее см. ниже); например, следующее снова дает что-то вроде My %USERNAME% is jdoe:

      echo My ^%USERNAME^% is %USERNAME%
      
    • В двойных кавычках нельзя убежать % на всех, но есть обходные пути:

      • Вы можете использовать строки без кавычек, как указано выше, что затем требует от вас дополнительно ^ - избегать всех других метасимволов оболочки, что является громоздким; эти метасимволы: <space> & | < > "

      • В качестве альтернативы, если целевая программа поддерживает ее (должна работать с большинством двоичных исполняемых файлов, но не с пакетными файлами), вы можете представить % символы. как "%"; например:

        echo "My "%"USERNAME"%" is %USERNAME%"
        
    • Из языков сценариев, если вы знаете, что вызываете двоичный исполняемый файл, вы можете избежать всей проблемы, отказавшись от вызывающих оболочку функций в пользу "безоболочечных" вариантов, таких как использование execFileSync вместо execSync в Node.js.


Необязательная справочная информация для командной строки (интерактивная):

Наконечник шляпы, чтобы jeb его за помощь в этом разделе.

В командной строке (в интерактивном режиме) % технически не может быть вообще спасен; в то время как ^ как правило, cmd.exe побег персонаж, это не относится к %,

Как уже говорилось, не существует решения для строк в двойных кавычках, но есть обходные пути для строк без кавычек:

Причина, по которой " ^ "Разрушитель имен" (что-то вроде ^%USERNAME^% ) работает это:

  • Это "разрушает" имя переменной; то есть в приведенном выше примере cmd.exe ищет переменную с именем USERNAME^ которого (надеюсь) не существует.

  • В командной строке - в отличие от пакетных файлов - ссылки на неопределенные переменные сохраняются как есть.

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

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

В основном гипотетическая оговорка: ^ на самом деле является допустимым символом в именах переменных (см. пример jeb в комментариях); если имя вашей переменной заканчивается ^ Просто поместите "разрушительный" ^ где - то еще в имени переменной, если она не находится рядом с другой ^ (поскольку это вызвало бы ^ появляться в результирующей строке).
Тем не менее, в (очень маловероятном) случае, что ваша переменная имеет имя, такое как ^b^, не повезло тебе.

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

Как "уйти" внутри командного файла с возможностью изменения файла ** Исходный вопрос касается сгенерированного файла, который не может быть изменен, но содержит такие строки, как:

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

Частично это можно решить, вызвав сценарий с соответствующими аргументами (%1, %2,...)

       @echo off

set "per=%%"
call generated_file.bat %%per%%1 %%per%%2 %%per%%3 %%per%%4

Это просто устанавливает аргументы:

       arg1="%1"
arg2="%2"
...

Как добавить буквальный знак процента в командную строку

mklement0 описывает проблему, заключающуюся в том, что избежать знака процента в командной строке сложно, а внутри кавычек это кажется невозможным.

Но, как всегда, ее можно решить с помощью небольшой хитрости.

       for %Q in ("%") do echo "file%~Q20name.txt"

%Q содержит "%" и %~Q расширяется только до %, независимо от котировок.

Или чтобы избежать %~ использовать

       for /F %Q in ("%") do echo "file%Q20name.txt"

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

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

Другие вопросы по тегам