Eu tenho uma pasta com cerca de 5000 .ts
arquivos que quero concatenar em um. Eles seguem o formato de nomenclatura de chunk_n
so por exemplo chunk_50
, chunk_51
, chunk_52
etc. Quando eu executo o comando de cópia do windows assim:
copy /b *.ts final.ts
Ele não itera por eles em ordem numérica normal. Ele começará a concatená-los nesta ordem:
chunk_100
, chunk_1000
, chunk_1001
, chunk_1002
, chunk_1003
, chunk_1004
, chunk_1005
, chunk_1006
, chunk_1007
, chunk_1008
, chunk_1009
,chunk_101
e assim por diante.
Parece que ele não olha para o nome do arquivo inteiro quando itera sobre eles. Mesmo se eu remover o de chunk_
antemão e apenas nomeá-los de 1 a 5000, o problema ainda persistirá. Este é um comportamento pretendido? E existe uma maneira melhor para eu concatenar todos esses arquivos?
Na maioria dos programas, a ordem numérica nunca foi a ordem normal. Apenas recentemente os gerenciadores de arquivos (como o Windows Explorer) começaram a classificar arquivos usando "classificação natural", mas o
copy
comando e o*
não foram alterados de acordo.Em vez disso, a expansão classifica os nomes dos arquivos por sua ordem de bytes
*
ASCII , comparando cada caractere separadamente. Por exemplo, com "chunk_1000.ts" vs "chunk_101.ts" (a extensão faz parte do nome), os primeiros 8 bytes ( ) são iguais, e então você tem < (zero é ASCII 48, um é ASCII 49) e, portanto, < – mesmo que mais dígitos sigam, eles não são considerados parte de um "número" inteiro.chunk_10
0
1
chunk_100(0.ts)
chunk_101(.ts)
(A ordem de bytes é a maneira mais direta de classificar nomes - tudo o que é necessário é comparar diretamente dois locais de memória. Essa simplicidade era importante quando a RAM era medida em kilobytes. Agora tem sido o caso por uns bons 50 anos, então é praticamente impossível para mudar agora, devido a muitos scripts que dependem do comportamento existente.)A solução mais simples é preencher todos os números com uma largura fixa, por exemplo
chunk0050
chunk0100
.Uma solução alternativa diferente, disponível em shells mais avançados, como PowerShell ou Bash, é obter e classificar a lista de entradas como uma etapa separada. Por exemplo, no Linux, você usaria os comandos externos 'sort' ou 'natsort' para obter a ordem desejada (eles não são exatamente parte do Bash, mas geralmente estão presentes onde quer que o Bash esteja presente):
No PowerShell,
Sort-Object
pode ser dado um comparador personalizado; não há um pré-definido para a ordem "natural" (numérica), mas a partir daqui você pode emprestar uma linha:Os nomes dos arquivos são nomes , não números, então eles são comparados como strings de texto, usando a ordem lexicográfica.
chunk_1
vem anteschunk_10
que vem anteschunk_10a
que vem anteschunk_1z
que vem anteschunk_2
.Se zsh estiver disponível, você pode usar o seguinte comando:
Isso aproveita uma combinação de recursos do zsh:
n
aplica a classificação numérica de partes inteiras em vez da ordem lexicográfica padrão, portanto,chunk9.ts
é classificado anteschunk10.ts
de .Se utilitários básicos do tipo Unix também estiverem disponíveis, você pode usar o
cat
comando para concatenar arquivos:Zsh está disponível através de WSL (
sudo apt-get install zsh
), Cygwin e provavelmente outras distribuições de software livre para Windows.O comando do Windows
copy
é umCMD.EXE
comando interno. Ele não faz nenhuma classificação em suas expansões curinga. Esse comportamento remonta a pelo menos o MS-DOS 6.22COMMAND.COM
(não tenho nada anterior à mão para testar). Acontece que seu sistema de arquivos NTFS armazena nomes de arquivos em uma estrutura de árvore B que tem o efeito de enumerá-los em uma ordem que se aproxima da ordem de classificação léxica.Mais informações estão disponíveis no blog Old New Thing:
Por que o NTFS e o Explorer discordam na classificação de nomes de arquivos?
Em que ordem o comando DIR organiza os arquivos se nenhuma ordem de classificação for especificada?
TBH Eu acho que todas essas digressões em coisas como ordenação de bytes e etc. estão turvando as águas um pouco. Aqui está o ponto mais importante e básico que todos deveriam entender sobre ordenação em computadores:
Por padrão (ou seja, a menos que seja aplicado um algoritmo mais avançado que faça uma interpretação mais complexa das entradas), um computador classificará dados de string (como nomes de arquivos) comparando-os caractere por caractere, começando pelo primeiro. (Que é provavelmente o mais à esquerda, embora não necessariamente porque existem linguagens RTL.)
Isso é correto para a classificação de strings de texto, mesmo que tenham comprimentos diferentes. A maioria de nós esperaria que uma lista de nomes fosse classificada assim, por exemplo:
A letra mais significativa em uma string, quando se trata de ordenação, é a primeira, e o comprimento é irrelevante, exceto que as strings com comprimento total mais curto vêm antes das mais longas que contêm o mesmo texto inicial.
O problema é que isso é exatamente errado para números, que devem ser comparados com seus últimos dígitos alinhados. Quando estamos falando de números, o comprimento é o fator mais crítico: valores maiores são SEMPRE maiores que os menores, pois possuem dígitos mais significativos. (Suponha que estamos falando de números inteiros aqui; pontos decimais complicam ainda mais as coisas.) O fato de o comprimento ser mais significativo do que o valor é o motivo pelo qual normalmente alinhamos listas de números à direita.
A classificação alfabética às vezes pode produzir os mesmos resultados que a classificação numérica, mas somente quando os números são representados como strings de igual comprimento. É por isso que o preenchimento com
0
s corrigiu seu problema. A classificação ainda não está fazendo uma comparação numérica adequada, no entanto. (É comparar os números como strings, caractere por caractere da esquerda para a direita. Mas acontece que comparar dígito por dígito, da esquerda para a direita, é exatamente como você compararia dois números de n dígitos. O mais significativo dígito está à esquerda e o menos significativo está à direita.)A questão de classificação também é o motivo pelo qual tantos na indústria de computação (inclusive eu) são grandes defensores do padrão ISO-8601 para representar datas como AAAA-MM-DD. Assim como os números, as datas nesse formato serão classificadas corretamente pela classificação alfabética "burra", porque os componentes são ordenados da esquerda para a direita, do mais para o menos significativo, que é exatamente como funciona a classificação alfabética. A ordenação não está interpretando a string YYYY-MM-DD como uma data, nem está interpretando-a como um número...
Aqui está outra abordagem do PowerShell :
Alias: