Игнорировать знак процента в пакетном файле - PullRequest
28 голосов
/ 15 декабря 2009

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

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

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

Сбой при попытке найти файл с именем:

\\myserver\myfolder\file0name.txt

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

Ответы [ 5 ]

46 голосов
/ 22 февраля 2012

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

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

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

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

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

18 голосов
/ 15 июля 2015

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

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

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

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

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

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

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

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

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

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


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

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

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

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

Причина, по которой работает трюк "^ name-disrupter" (что-то вроде ^%USERNAME^%) :

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

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

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

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

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

14 голосов
/ 28 марта 2011

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

1 голос
/ 29 июня 2015

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

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

0 голосов
/ 15 декабря 2009

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

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

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

.
...