Folder Prey has 
    "Deer.txt",
    "Antelope.txt",
    "Rabbit.txt"  
Folder Predator has 
    "Shark.txt",
    "Bear.txt",
    "Cougar.txt"  
Folder Habitat has 
    "Forest.txt",
    "Ocean.txt",
    "Desert.txt"

Как мне сгенерировать все 27 возможных комбинаций, используя файл .bat? Сложность в том, что количество папок не является статичным. Кто-то может добавить Папку Еду позже или удалить Среду Папки. Может ли файл .bat быть написан, чтобы справиться с этим?

Выход будет:

Deer_Shark_Forest
Deer_Shark_Ocean
Deer_Shark_Desert
Deer_Bear_Forest
Deer_Bear_Ocean
Deer_Bear_Desert
Deer_Cougar_Forest
Deer_Cougar_Ocean
Deer_Cougar_Desert
Antelope_Shark_Forest
Antelope_Shark_Ocean
Antelope_Shark_Desert
Antelope_Bear_Forest
Antelope_Bear_Ocean
Antelope_Bear_Desert
Antelope_Cougar_Forest
Antelope_Cougar_Ocean
Antelope_Cougar_Desert
Rabbit_Shark_Forest
Rabbit_Shark_Ocean
Rabbit_Shark_Desert
Rabbit_Bear_Forest
Rabbit_Bear_Ocean
Rabbit_Bear_Desert
Rabbit_Cougar_Forest
Rabbit_Cougar_Ocean
Rabbit_Cougar_Desert

Уверяю вас, это не домашнее задание. Я хотел бы написать это как командный файл.

3 ответа3

2

Вы можете сделать это с помощью следующего пакетного файла:

@echo off
setlocal enabledelayedexpansion
set first_pass=yes
copy nul temp2.txt > nul
for /d %%D in (*) do (
    for %%F in ("%%D"\*) do (
        if !first_pass! == yes (
            echo %%~nF >> temp2.txt
        ) else (
            for /f "delims=" %%L in (temp1.txt) do (
                echo %%~nF_%%L >> temp2.txt
            )
        )
    )
    set first_pass=no
    del temp1.txt 2> nul
    rename temp2.txt temp1.txt
)

Это создает файл с именем temp1.txt .  (Конечно, скрипт можно легко изменить, чтобы использовать другое имя файла и / или для отображения результатов на экране.)  Это вывод, который я получил:

Antelope_Bear_Desert
Antelope_Bear_Forest
Antelope_Bear_Ocean
Antelope_Cougar_Desert
Antelope_Cougar_Forest
Antelope_Cougar_Ocean
Antelope_Shark_Desert
Antelope_Shark_Forest
Antelope_Shark_Ocean
Deer_Bear_Desert
Deer_Bear_Forest
Deer_Bear_Ocean
Deer_Cougar_Desert
Deer_Cougar_Forest
Deer_Cougar_Ocean
Deer_Shark_Desert
Deer_Shark_Forest
Deer_Shark_Ocean
Rabbit_Bear_Desert
Rabbit_Bear_Forest
Rabbit_Bear_Ocean
Rabbit_Cougar_Desert
Rabbit_Cougar_Forest
Rabbit_Cougar_Ocean
Rabbit_Shark_Desert
Rabbit_Shark_Forest
Rabbit_Shark_Ocean

Заметки:

  • Очевидно, что при этом используется подстановочный знак * , и поэтому порядок вывода зависит от порядка, в котором Windows расширяет подстановочный знак.  В моей системе, учитывая алфавитные записи каталога, * расширяется в алфавитном порядке.  Это может отличаться в системах, которые используют языки, отличные от английского, и / или это может быть изменено настройкой конфигурации.  В следующих двух пунктах я предполагаю, что используется алфавитный порядок.
  • В каждой папке имена расположены в алфавитном порядке; Например, Антилопа перед Оленем и т. д., Медведь перед Кугаром и т. д.
  • В соответствии с желаемым выводом, указанным в вашем вопросе, папки выводятся в обратном алфавитном порядке; то есть, Prey_Predator_Habitat.
  • Любое из вышеперечисленного может быть изменено (хотя и не элегантно).


  • setlocal enabledelayedexpansion позволяет нам обрабатывать переменные в циклах.
  • copy nul temp2.txt > nul создает второй временный рабочий файл.  > nul подавляет нормальное 1 file(s) copied. статус.
  • for /d %%D in (*) do цикл по всем папкам в текущем каталоге.  Переменная %%D будет последовательно принимать значения Habitat , Predator и Prey - или любые другие папки в текущем каталоге, когда вы запускаете пакетный файл.
  • for %%F in ("%%D"\*) do циклически перебирает все файлы в каталоге %%D ; т. е. каталог, на который мы сейчас обращаемся из внешнего цикла.  Переменная %%F будет последовательно принимать значения, такие как Habitat\Desert.txt , Habitat\Forest.txt и Habitat\Ocean.txt .  Кавычки позволяют это работать, даже если имя каталога содержит пробел (ы).

    Если в папке есть другие файлы, они также будут включены.  Если вы хотите смотреть только на файлы .txt изменить for заявления в for %%F in ("%%D"\*.txt) do

  • !first_pass! это просто переменная first_pass .  Обычно это пишется %first_pass% , но нам нужно использовать этот синтаксис, потому что мы в цикле.  (Это работает только потому, что мы его включили с помощью setlocal enabledelayedexpansion .)
  • first_pass - yes пока мы обрабатываем первый каталог; то есть Habitat .  В этом случае мы просто записываем имя файла в файл temp2.txt ; поэтому, когда цикл for %%F in ("%%D"\*) do завершится, temp2.txt будет содержать
    пустынный
    лес
    Океан
    потому что %%~nF оценивает только базовый файл п Ame часть пути доступа к файлу в %%F Если вы хотите включить напряжение .txt e x , используйте %%~nxF вместо %%~nF .
  • Оповещение о спойлере: когда мы выполняем внешний (for /d %%D) второй и третий (и т.д.) Раз , first_pass - это no а temp1.txt - это temp2.txt из предыдущего прохода.
  • Таким образом, на втором и третьем проходах (и т.д.) Мы выполняем for /f "delims=" %%L in (temp1.txt) do , который проходит по строкам в temp1.txt , устанавливая %%L для содержимого из линий. "delims=" - это строка параметров, которая указывает, что строки не следует разбивать на слова.  Это позволяет этому пакетному файлу работать, даже если имена файлов содержат пробелы.
  • Например, на втором проходе (%%D = Predator) внешнего цикла, когда мы делаем первый проход (%%F = Predator\Bear.txt) второго цикла, temp1.txt такой же, как показано выше для temp2.txt и temp2.txt пустые.
  • Для каждой строки (%%L) из temp1.txt мы делаем echo %%~nF_%%L >> temp2.txt , который записывает текущее имя файла, символ подчеркивания _ и текущую строку (из temp1.txt) в temp2.txt (добавление).  Таким образом, после первого прохода (Bear) второго цикла, включая полный запуск третьего цикла, temp2.txt будет содержать
    Bear_Desert
    Bear_Forest
    Bear_Ocean
    Второй проход (Cougar) второго цикла добавится
    Cougar_Desert
    Cougar_Forest
    Cougar_Ocean
    на temp2.txt и так далее.
  • К тому времени, когда мы достигнем третьего прохода (%%D = Prey) внешнего цикла, temp1.txt - это temp2.txt из предыдущего прохода, содержащий девять строк (шесть из которых показаны выше).  Затем происходит то же самое (с разными значениями), что и раньше; %%F устанавливается в Prey\Antelope.txt , и поэтому каждая строка в temp1.txt копируется в temp2.txt с добавлением Antelope_ , и мы получаем
    Antelope_Bear_Desert
    Antelope_Bear_Forest
    Антилопа - медведь - морская антилопа - кугар - десерт
    Antelope_Cougar_Forest
  • Как и предполагалось, когда мы заканчиваем второй цикл и добираемся до конца первого цикла, мы устанавливаем first_pass в no , удаляем текущий temp1.txt (если есть; если его еще нет, подавляем сообщение об ошибке) и переименуйте temp2.txt в temp1.txt .

Таким образом, мы получаем файл длиной 27 строк (Num (Habitat) × Num (Predator) × Num (Prey)). Вы можете добавлять и удалять папки и файлы, потому что в скрипте ничего не прописано, даже количество папок.

  • Если есть папка (например, Job_Titles), которая не содержит файлов, то выходных данных не будет (потому что 3 × 0 × 3 × 3 = 0).  Фактически, в этом случае вышеупомянутый пакетный файл генерирует кучу сообщений об ошибках и либо пустой файл temp1.txt (ожидаемое поведение), либо вообще никакого файла.  Это, конечно, можно исправить.
  • Этот сценарий был разработан для обработки имен файлов или каталогов, содержащих пробелы, и был протестирован в этой ситуации (и, похоже, он работает правильно), но могут быть некоторые крайние случаи, которые я не учел.
  • Неизбежно, вывод будет неоднозначным, если любое из имен файлов содержит _ (подчеркивание).  Например, Antelope_Mountain_Lion_Forest является неоднозначным.
1

Вы можете использовать PowerShell:

$categories = gci -Directory | % {$_.Name}
Function AddCombos([int]$catPos, $root) {
    gci ".\$($categories[$catPos])\*.txt" | % {
        $memberTitle = [IO.Path]::GetFileNameWithoutExtension($_.Name)
        If ($catPos -eq ($categories.Length - 1)) {
            $root + $memberTitle
        } Else {
            AddCombos ($catpos + 1) ($root + $memberTitle + '_')
        }
    }
}
AddCombos 0 ''

Во-первых, этот скрипт получает имена всех категорий (например, "Prey") и помещает их в список $categories . Затем он определяет рекурсивную функцию. AddCombos получает все файлы в категории, проиндексированные $catPos . Если он не относится к последней категории, он выводит завершенную строку. В противном случае он вызывает себя после добавления текущего члена (например, "Олень") в строку незавершенного производства и увеличения $catPos чтобы указать, что следует искать следующую категорию. После определения этой функции скрипт вызывает ее, начиная с первой категории (индекс 0) и с пустой строкой в качестве незавершенного производства.

Обратите внимание, что порядок категорий определяется в алфавитном порядке. Так как имена папок не используются в выходных данных, вы можете назвать их так, чтобы они выполнялись в том порядке, в котором вы хотите. Сценарий использует заголовки текстовых файлов в выходных данных, но если вы хотите контролировать их порядок, переименовывая файлы, вы можете изменить $memberTitle = :

$memberTitle = (gc $_)[0]

Это занимает первую строку содержимого каждого файла вместо его заголовка.

Этот скрипт может обрабатывать любое количество категорий и любое количество членов в каждой категории.

Чтобы запустить его, сохраните его как файл .ps1 и следуйте инструкциям в разделе «Включение сценариев» вики-тега PowerShell. Затем вы можете запустить его из командного файла следующим образом:

powershell .\myscript.ps1
0
@echo off
    setlocal enableextensions disabledelayedexpansion

    for %%t in ("%temp%\%random%%random%%random%.tmp") do (
        >"%%~ft" echo(*
        for /d %%d in (*) do >nul 2>&1 dir /a-d "%%d" && for /f "tokens=* delims=*" %%l in ('
            type "%%~ft" ^& ^>"%%~ft" break
        ') do for %%f in ("%%d\*") do (
            >>"%%~ft" (if "%%~l"=="" (echo(%%~nf) else (echo %%l_%%~nf))
        )
    ) & type "%%~ft" & del "%%~ft"

Он сгенерирует временный файл (на который ссылается %%t), где объединяются выходные строки.

Для каждого каталога (%%d) временный файл читается, очищается, и для каждой строки (%%l) во временном файле он снова отображается с каждым файлом (%%f) в текущей папке, объединенным

После объединения всех имен файлов временный файл отправляется на консоль и удаляется.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .