Windows复制命令以非数字顺序连接多个文件

Don*_*liu 12 windows-10 windows-terminal

我有一个包含大约 5000 个.ts文件的文件夹,我想将它们合并成一个。它们遵循 so 的命名格式,例如 、chunk_nchunk_50。当我像这样运行 Windows 复制命令时:chunk_51chunk_52

copy /b *.ts final.ts

它不会按正常的数字顺序迭代它们。它将开始按以下顺序连接它们:

chunk_100,,,,,,,,,,,,,,,,chunk_1000chunk_1001chunk_1002chunk_1003chunk_1004chunk_1005chunk_1006chunk_1007chunk_1008chunk_1009chunk_101

等等。

当它迭代它们时,它似乎不会查看整个文件名。即使我chunk_事先删除它们并将它们全部命名为 1 到 5000,问题仍然存在。这是有意的行为吗?有没有更好的方法让我连接所有这些文件?

use*_*686 25

在大多数程序中,数字顺序从来都不是正常的顺序。直到最近,文件管理器(例如Windows资源管理器)才开始使用“自然排序”对文件进行排序,但命令copy和并*没有相应改变。

\n

相反,*扩展按文件名的 ASCII字节顺序对文件名进行排序,并分别比较每个字符。例如,对于“chunk_1000.ts”与“chunk_101.ts”(扩展名是名称的一部分),前 8 个字节 ( chunk_10) 相等,然后您有0\xc2\xa0<\xc2\xa0 1(零是ASCII 48,一个是 ASCII 49),因此chunk_100(0.ts)\xc2\xa0<\xc2\xa0 chunk_101(.ts)\xe2\x80\x93 即使后面有更多数字,它们也根本不被视为整个“数字”的一部分。

\n

(字节顺序是对名称 \xe2\x80\x93 进行排序的最直接方法,所需要的只是直接比较两个内存位置。当 RAM 以千字节为单位进行测量时,这种简单性非常重要。现在,对于一个好的系统来说,情况就是如此。 50 年了,所以现在几乎不可能改变,因为许多脚本依赖于现有的行为。)

\n

最简单的解决方法是将所有数字填充到固定宽度,例如chunk0050 chunk0100

\n

PowerShell 或 Bash 等更高级的 shell 中提供了一种不同的解决方法,即作为单独的步骤获取输入列表并对其进行排序。例如,在 Linux 上,您可以使用外部“sort”或“natsort”命令来获取所需的顺序(它们并不完全是 Bash 的一部分,但通常出现在 Bash 存在的任何地方):

\n
(printf \'%s\\n\' chunk*.ts | sort -V | xargs -d\'\\n\' cat) > allchunks.ts\n
Run Code Online (Sandbox Code Playgroud)\n

在PowerShell中,Sort-Object可以给出自定义比较器;没有预定义的“自然”(数字)顺序,但从这里您可以借用一行:

\n
$ToNatural = { [regex]::Replace($_, \'\\d+\', { $args[0].Value.PadLeft(20) }) }\n$filenames = Get-ChildItem chunk*.ts | Sort-Object $ToNatural\n$filenames = $filenames -join "+"\ncmd /c "copy $filenames allchunks.ts"\n
Run Code Online (Sandbox Code Playgroud)\n

  • 字节排序之所以存在,是因为它是“可预测的”:一个程序的智能排序可能与另一个程序的不同,但字节排序始终是相同的。这使得弄清楚命令或程序将要执行的操作变得更加容易。 (11认同)
  • @user1652994 如果你有 bash 可用,你也可以做 `cat chunk_{1..5000}.ts &gt; out.ts` :) (3认同)
  • 感谢你的回答。我刚刚编写了一个 bash 脚本,将必要的填充添加到需要它的文件名中。之后一切都很顺利。 (2认同)

Gil*_*il' 5

文件名是名称,而不是数字,因此它们将作为文本字符串进行比较,并使用字典顺序。chunk_1来之前chunk_10,来之前chunk_10a,来之前chunk_1z,来之前chunk_2

如果zsh可用,您可以使用以下命令:

<*.ts(n) >final.ts
Run Code Online (Sandbox Code Playgroud)

这利用了 zsh 功能的组合:

如果基本的类 Unix 实用程序也可用,您可以使用以下cat命令来连接文件:

cat *.ts(n) >final.ts
Run Code Online (Sandbox Code Playgroud)

Zsh 可以通过WSL ( sudo apt-get install zsh)、Cygwin以及可能的其他 Windows 免费软件发行版获得。