Есть ли способ получить оболочку Windows cmd для расширения пути подстановки?


37

Иногда неспособность оболочки cmd расширять пути подстановки может быть неудобством. Мне пришлось передать 100 файлов из каталога в программу, и я не смог набрать * .ext. Вместо этого я использовал msw 'ls', чтобы вывести список в файл, а затем заменил символы новой строки пробелами, скопировал и вставил в cmd. Совсем кошмар.

Я подозреваю, что ответ будет отрицательным, но кто-нибудь имел дело с этим или придумал какой-нибудь способ облегчить это?


2
Рассматривали ли вы вместо этого что-то вроде Powershell?

I suspect the answer will be no, but has anyone dealt with this or come up with any way to make this easier? На самом деле, у меня возникла противоположная проблема, я пытаюсь найти способ заставить интерпретатор команд обрабатывать свой список как строки и не допускать его интерпретацию как подстановочных знаков. Например, for %i in (foobar baz really?) do @echo %iбудет рассматривать последний элемент ( really?) в качестве имени файла шаблона, и пропустить его , если нет файлов с именем really1, reallyzи т.д. ☹
— Synetech

1
@Synetech - ?недопустимый символ для имен файлов в файловой системе Windows. Символ может быть интерпретирован только как подстановочный знак. См. Имена файлов, путей и пространств имен в MSDN и Использование подстановочных знаков в TechNet.
— 15:15

Ответы:


18

DOS и, следовательно, Windows ' cmd.exeникогда не поддерживали расширение подстановочными символами в оболочке. Это всегда было за приложением, чтобы сделать расширение.

Это означает, что вам всегда придется искать другой маршрут, если вы используете приложение, которое не поддерживает расширение. Ты мог бы:

  • Используйте цикл FOR для запуска некоторых команд со всеми интересующими вас файлами
  • Используйте, dir /b > list.txtчтобы использовать dirкоманду, чтобы выполнить расширение и поместить список файлов в текстовый файл (тогда вы могли бы использовать что-то вроде формулы Excel, если вы действительно хотите создать список команд для вставки cmd, или вы можете использовать Excel транспонировать ячейки так, чтобы все имена файлов были в одной строке.)

Он объяснил, что вывод результатов dir в файл будет кошмаром, а процесс фильтрации и копирования выполняется вручную. Ответ wmz и, конечно, мой, будут работать без ручной фильтрации содержимого файлов.
— wullxz

1
@wullxz: Возможно, но для тех, кто не знаком с Powershell и хочет сделать это как разовое, это может быть значительно быстрее - и идея этого сайта состоит в том, чтобы предоставить полезные решения для людей всех уровней квалификации, к которым можно обратиться сейчас и в будущее, так что на самом деле нет нужды отговаривать меня, потому что вы думаете, что мой ответ не так хорош, как ваш.
— Malvineous

1
«DOS и, следовательно, Windows cmd.exe, никогда не поддерживали расширение подстановочными символами в оболочке». - Не соответствует действительности в соответствии с Microsoft. См. Использование подстановочных знаков в TechNet. (Но я думаю, что вы правы на практике: o. В противном случае я бы здесь не пытался выяснить, почему файлы не совпадают)
— jww

1
@jww: ссылка, которую вы разместили, объясняет стандартное использование подстановочных знаков, но я не вижу никаких упоминаний о том, что они были расширены оболочкой. В отличие от UNIX (и позже Linux и Mac), Microsoft оставила расширение подстановочного знака для каждого отдельного приложения для реализации, передавая параметры командной строки как есть.
— Malvineous

1
Команда DOS 'dir Filespec / b' работает очень хорошо, потому что она создает список файлов, по одному на строку. С дополнительным ключом '/ s' имена файлов полностью определены (абсолютные) и могут быть легко переданы через цикл for любой другой программе командной строки, которая принимает имя файла. Это лучшее, что мы можем сделать, поскольку Windows не имеет надлежащей функции глобализации.
— Дэвид А. Грей,

9

Просто используйте Powershell, который предустановлен в Windows 7. Powershell способен запускать команды cmd и понимает подстановочные знаки в любом месте пути.

Чтобы запустить Powershell, просто введите «powershell» в поле поиска в меню «Пуск» и нажмите Enter.


Если приложение ожидает строку со всеми именами файлов, это правильный сценарий:

$delimiter = " "
[string]$files = $nothing ; ls *.txt | % { $files += $_.fullname + $delimiter } ; application.exe $files

Измените $delimiter = " "на, $delimiter = ","если ваше приложение ожидает разделенный запятыми список имен файлов.

Объяснение кода:

  • [string]$files = $nothing - создает пустую переменную типа string
  • ; - это разделитель для нескольких команд, а не конвейер!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - получает список всех текстовых файлов и создает строку со всеми именами файлов, разделенными разделителем
  • application.exe $files - вызывает приложение и передает ему список файлов

Вы даже можете рекурсивно искать шаблон файла, добавив -recurseего ls *.txtтак, чтобы весь код выглядел так:

$delimiter = " "
[string]$files = $nothing ; ls *.txt -recurse | % { $files += $_.fullname + $delimiter } ; application.exe $files

Изменить:
чтобы избежать раздражения, lsи dirпсевдонимы Get-ChildItemи %псевдоним ForEach-Object. Я держу свой код с использованием псевдонимов, потому что он короче.

РЕДАКТИРОВАТЬ 2018/04/25:
в 2012 году я был довольно новым для PowerShell. Конечно, есть более простой способ, хотя он не так прост, как способность unix / linux к расширению glob:

app.exe $(ls *.txt | % {$_.FullName})

Объяснение:

  • $ () сначала вычислит выражение внутри и заменит себя выводом этого выражения (так же, как обратные пометки в bash)
  • ls *.txt получает объекты FileInfo всех файлов, которые соответствуют глобу *.txt
  • поскольку PowerShell является объектно-ориентированным, мы должны вывести полное имя каждого объекта FileInfo. Простое присвоение имени атрибуту / свойству в PowerShell выводит его по умолчанию. % { $_.FileName }делает это для нас. %перебирает все возвращаемые элементы lsи выводит каждый объект FileName.

2
Несмотря на то, что PS, безусловно, способен выполнить запрос, и совет для ознакомления с ним является здравым - это не так просто, как вы предлагаете. Запуск start notepad++ *.txt(с целью открыть все TextFiles - используется Notepad ++ , как это делает обрабатывать несколько имен) не добьешься
— WMZ

1
Вы можете обойти это с dir *.txt | % { notepad++.exe $_ }. Я попробовал это с простым блокнотом, потому что у меня нет notepad ++, и это сработало. Команда получает список всех txt-файлов в текущем каталоге, передает список следующей команде, которая проходит по списку и выполняет notepad ++ с именем файла в качестве параметра.
— wullxz

да, но это не эквивалентно Подумайте о том, grep "a b c"чтобы найти любую из перечисленных строк, где «ab c» будет расширен список
— wmz

5
Выполнение команды со списком элементов в качестве параметра не эквивалентно многократному выполнению команды с каждым элементом из списка в качестве параметра. Другой пример: copy a+b+c resultа copy a result copy b result copy c result. (и в PS существует утилита типа grep, она называется select-string)
— wmz

1
upvoted, кстати, жаль, что OP не хочет вмешиваться, чтобы объяснить ...
— wmz

8

Это даст вам список, а также поместит его в переменную с именем expanded_list. Поместите его в командный файл и запустите myBatchFile name myPattern. Заключите шаблон в кавычки, если он содержит пробелы. Совпадает с файлами, без каталогов. Запуск без параметров соответствует всем.

@echo off
set expanded_list=
for /f "tokens=*" %%F in ('dir /b /a:-d "%~1"') do call set expanded_list=%%expanded_list%% "%%F"

echo expanded_list is: 
echo %expanded_list%

Затем вы можете запустить свою команду с my_command_exec %expanded_list%

ПРЕДУПРЕЖДЕНИЕ! Максимальный размер переменной cmd составляет 8191 символ (начиная с XP), поэтому его можно переполнить! Вы не можете рассчитывать на утилиту, чтобы всегда дать вам полный список. С другой стороны, максимальная длина строки cmd также равна 8191, поэтому вы не сможете выполнить ее в любом случае.


Обратите внимание, что если аргументы не указаны, то для параметра extended_list будут установлены все файлы в текущем каталоге, которые могут быть, а могут и не быть желаемыми, поэтому может потребоваться добавить проверку на отсутствие аргументов (например, если "% 1" == "" ...)
— JasonM1

3

Это работает в cmd.exe

dir /b *.ext

или

echo | dir /b *.ext

Это работает только для имени файла, а не какой-либо части пути. Например dir /b TortoiseSVN\bin\sv*.exeпокажет svn.exeи svnadmin.exe. Но dir /b TortoiseSVN\bi*\svn.exeпоказывает синтаксическую ошибку.
— Styfle

1
проверить dir /s /b. Это дает вам полный путь.
— WesternGun

3

Обратите внимание, это в комментариях к постерам в отдельной ветке user619818 и styfle)

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

Примечание. Предполагается, что корневым каталогом для проверки того, под какими каталогами находятся все подкаталоги, является «C: \ My Program \ Root \», поскольку автор не указал путь, по которому расположены эти каталоги.

DIR /B /S "C:\My Program\Root\*.ext"

это даст полные пути к файлам и имена файлов исходных файлов.

если вам нужны только имена файлов, вы должны сделать следующее

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( Echo.%~nxA )

Итак, если вы хотите переместить все эти файлы из «C: \ My Program \ Root \ Sub Directories \ *. ext» в «D: \ Singlefolder \ *. ext», вы просто делаете это:

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( MOVE "%~A" "D:\Singlefolder\%~nxA" /Y )

Надеюсь, что это поможет другим в будущем. :)


1

Это старый, но с подсистемой Linux для Windows, довольно часто иметь bash в вашей переменной PATH. Если это так, то это может помочь вам:

bash -c 'cat *.txt'

обратите внимание, что одинарные кавычки не являются специальными в Windows cmd , поэтому, если вы запустите приведенную выше команду из cmd, она не будет работать. И это также относится к системам с Cygwin или другими средами bash
— phuclv
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.