Don*_*liu 12 windows-10 windows-terminal
我有一个包含大约 5000 个.ts文件的文件夹,我想将它们合并成一个。它们遵循 so 的命名格式,例如 、chunk_n等chunk_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和并*没有相应改变。
相反,*扩展按文件名的 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 即使后面有更多数字,它们也根本不被视为整个“数字”的一部分。
(字节顺序是对名称 \xe2\x80\x93 进行排序的最直接方法,所需要的只是直接比较两个内存位置。当 RAM 以千字节为单位进行测量时,这种简单性非常重要。现在,对于一个好的系统来说,情况就是如此。 50 年了,所以现在几乎不可能改变,因为许多脚本依赖于现有的行为。)
最简单的解决方法是将所有数字填充到固定宽度,例如chunk0050 chunk0100。
PowerShell 或 Bash 等更高级的 shell 中提供了一种不同的解决方法,即作为单独的步骤获取输入列表并对其进行排序。例如,在 Linux 上,您可以使用外部“sort”或“natsort”命令来获取所需的顺序(它们并不完全是 Bash 的一部分,但通常出现在 Bash 存在的任何地方):
\n(printf \'%s\\n\' chunk*.ts | sort -V | xargs -d\'\\n\' cat) > allchunks.ts\nRun Code Online (Sandbox Code Playgroud)\n在PowerShell中,Sort-Object可以给出自定义比较器;没有预定义的“自然”(数字)顺序,但从这里您可以借用一行:
$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"\nRun Code Online (Sandbox Code Playgroud)\n
文件名是名称,而不是数字,因此它们将作为文本字符串进行比较,并使用字典顺序。chunk_1来之前chunk_10,来之前chunk_10a,来之前chunk_1z,来之前chunk_2。
如果zsh可用,您可以使用以下命令:
<*.ts(n) >final.ts
Run Code Online (Sandbox Code Playgroud)
这利用了 zsh 功能的组合:
n应用整数部分的数字排序,而不是默认的字典顺序,因此chunk9.ts排序在 之前chunk10.ts。如果基本的类 Unix 实用程序也可用,您可以使用以下cat命令来连接文件:
cat *.ts(n) >final.ts
Run Code Online (Sandbox Code Playgroud)
Zsh 可以通过WSL ( sudo apt-get install zsh)、Cygwin以及可能的其他 Windows 免费软件发行版获得。
| 归档时间: |
|
| 查看次数: |
1844 次 |
| 最近记录: |