批量命令 select 多个文件并将其输出为单行

Batch command to select multiple file and output it as single line

我试图找到很多方法来完成这个但仍然没有希望(尝试使用数组等...)

有什么方法可以 select 目录中列出的文件的一部分并将其输出如下

例如,如果我输入 0-2,它输出为

00000\.MTS+00001.MTS+00002.MTS

相同,如果我输入 3-5,

00003\.MTS+00004.MTS+00005.MTS

示例文件夹列表

2022-03-24  00:14    \<DIR\>          .
2022-03-24  00:14    \<DIR\>          ..
2022-03-23  15:47         5,025,792 00000.MTS
2022-03-23  15:47         4,958,208 00001.MTS
2022-03-23  15:47         3,938,304 00002.MTS
2022-03-23  15:47         9,185,280 00003.MTS
2022-03-23  15:48         9,179,136 00004.MTS
2022-03-23  15:48         3,028,992 00005.MTS

我尝试这样做的原因是因为我想加入 MTS 文件而不用在命令中一个一个地输入。原来的命令就像

copy /b 00000.MTS+00001.MTS+00002.MTS+00003.MTS+00004.MTS+00005.MTS "C:\Users\Desktop\1.MTS"

希望可以使用批处理命令
第一名:0-2

copy /b 00000.MTS+00001.MTS+00002.MTS "C:\Users\Desktop\1.MTS"

第二名:3-5

copy /b 00003.MTS+00004.MTS+00005.MTS "C:\Users\Desktop\2.MTS"

是否可以在 bat 中完成此操作?

我确实尝试使用 for 循环来生成文件列表,

setlocal enabledelayedexpansion
set /P "mts1=MTS SET 1 : "
for %%n in (%mts1%) do (
echo !FILE_LIST\[%%n\]!+
)

但好像只显示全部,而且每个文件都换行,不能用在copy /b

@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory and destination directory are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files\t w o"
SET "destdir=%sourcedir%"

:: Do we have 2 arguments?
IF "%~2" equ "" ECHO need 2 arguments&GOTO :eof

:: calculate the destination filename
SET /a destfile=0
:destloop
SET /a destfile+=1
IF EXIST "%destdir%\%destfile%.MTS" GOTO destloop

:: change to source directory
PUSHD "%sourcedir%"

:: then build the list of files to concatenate
SET "sourcelist="
:again
FOR /f "tokens=1*delims=" %%b IN ('dir /b /a-d /on 0*.MTS ') DO (
 SET "candidate="
 SET /a candidate=1%%~nb 2>NUL
 IF DEFINED candidate (
  SET /a serial=candidate -100000
  IF !serial! geq %1 IF !serial! leq %2 SET "sourcelist=!sourcelist!+%%~nxb"
  IF !SERIAL! GEQ %2 IF "%3" NEQ "" SHIFT&SHIFT&GOTO AGAIN

 )
)
IF DEFINED sourcelist COPY %sourcelist:~1% "%destdir%\%destfile%.MTS"   >nul
:: back to original directory
POPD

GOTO :EOF

第一步:通过递增计数器并查看该文件名是否已存在来获取目标文件名。

下一步:扫描以 0 开头的 .MTS 个文件名的基本目录列表。对于找到的每个候选人,将 candidate 设置为 empty 然后尝试在前面使用算术 set (set /a) 字符串 1 所以该数字变为,例如 100000。这是因为以 0 开头的数字被 cmd 视为八进制。如果结果字符串不是数字,set /a 将失败,将产生错误消息(2>nul 抑制错误消息)并且 candidate 将保持设置为 ,即。未定义。

如果定义了candidate,则减去加入的100000,检查结果是否大于等于第一个参数AND小于等于第二个参数。如果是这样,用 +.

前面的新名称构建 sourcelist

最后,使用子字符串进行复制,从 sourcelist 中删除前导 +

运行 具有两个参数的批处理,开始和结束编号,例如。 thisbatch 3 7


针对评论的修正:

插入标签 :again 并添加额外的行 IF !serial! geq %2...

当第一个范围结束时,将serial设置为当前的第三个参数。如果现在定义了 serial,移出前两个参数并重新开始,sourcelist 已经 part-built。

请注意,这允许使用任何对,因此 thisbatch 12 15 3 6thisbatch 12 14 3 7 6 11

一样有效

--- 小改版

@ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following settings for the source directory and destination directory are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files\t w o"
SET "destdir=%sourcedir%"

:: Do we have 2 arguments?
IF "%~2" equ "" ECHO need 2 arguments&GOTO :eof

:restart
:: calculate the destination filename
SET /a destfile=0
:destloop
SET /a destfile+=1
IF EXIST "%destdir%\%destfile%.MTS" GOTO destloop

:: change to source directory
PUSHD "%sourcedir%"

:: then build the list of files to concatenate
SET "sourcelist="
:again
IF /i "%1"=="E" GOTO docopy
FOR /f "tokens=1*delims=" %%b IN ('dir /b /a-d /on 0*.MTS ') DO (
 SET "candidate="
 SET /a candidate=1%%~nb 2>NUL
 IF DEFINED candidate (
  SET /a serial=candidate -100000
  IF !serial! geq %1 IF !serial! leq %2 SET "sourcelist=!sourcelist!+%%~nxb"
  IF !SERIAL! GEQ %2 IF "%3" NEQ "" SHIFT&SHIFT&GOTO AGAIN
 )
)
:docopy
IF DEFINED sourcelist COPY %sourcelist:~1% "%destdir%\%destfile%.MTS"   >nul
:: back to original directory
POPD
IF /i "%1"=="E" shift&GOTO restart

GOTO :EOF

这让您两全其美。

如果你有一个命令行 thisbatch 3 6 0 2 那么它将生成 1 个包含 3+4+5+6+0+1+2 的新文件。

如果你有一个命令行 thisbatch 3 6 0 2 E 12 15 0 2 E 1 4 那么它将生成 3 个新文件 3+4+5+6+0+1+2, 12+13+14+15+0+1+ 2 和 1+2+3+4.

每个 number-pair 的名称都像以前一样连接在一起。如果下一个“起始编号”是 E(无论哪种情况),则执行 copy 命令,将 E 移出,并使用超出 [ 的任何参数重新启动整个过程=39=] 通过返回到具有奇怪名称 :restart.

的标签

这可以在 cmd 提示符或 batch-file 脚本中使用。 function 构建所需数字的数组。所需的数字表示为类似于许多指定页码的应用程序的字符串(即:“1-3”或“3-5,7,10-12”)

Do-ConcatFiles.batDo-ConcatFiles.ps1 脚本放在同一目录中。如果您使用的是受支持的 windows 系统,则可以使用 PowerShell。

=== Do-ConcatFiles.bat

@ECHO OFF
powershell -NoLogo -NoProfile -File "%~dpDo-ConcatFiles.ps1" -PagesList 1-3,12 -Path ".\pageslist.txt"

=== Do-ConcatFiles.ps1

[CmdletBinding()]
param (
    [Parameter(Mandatory=$true)]
    [string]$PagesList = '1-3,5,7-12'

    ,[Parameter(Mandatory=$true)]
    [string]$Path = 'C:\src\t\pageslist\pageslist.txt'
)
function Get-PagesList([string]$PagesString) {
# Build an array of desired numbers.
$Pages = @()
$PagesString -replace '\s*' -split ',' |
    ForEach-Object {
        if ($_ -match '(\d*)\-(\d*)') {
            for ([int]$i = [int]$Matches[1]; $i -le [int]$Matches[2]; $i++) { $Pages += $i }
        } else { $Pages += $_ }
    }
return $Pages
}

<#  TEST FILE GENERATION
1..20 | ForEach-Object {
    $FileName = ('{0:000000}' -f $_) + '.txt'
    Set-Content -Path $FileName -Value $FileName -Encoding ascii
}
#>

Write-Verbose "Input PagesList = $PagesList"
Write-Verbose "Input result file is $Path"
$Pages = Get-PagesList($PagesList)
if ($Pages.Count -ne 0) {
    if (Test-Path -Path $Path) { Remove-Item -Path $Path }
    $Files = Get-ChildItem -Path '[0-9]*.txt'
    $Pages |
        ForEach-Object {
            foreach ($File in $Files) {
                if (($File -match '(\d*).txt') -and ([int]$Matches[1] -eq $_)) {
                    Write-Verbose "Appending file $File to $Path"
                    Get-Content -Path $File | Out-File -FilePath $Path -Append -Encoding ascii
                }
            }
        }
}