CLI do Windows equivalente a "sort-u"

Eu preciso de uma forma equivalente em um CLI do Windows para fazer o que eu seria capaz de fazer em Linux/UNIX em piping para mostrar valores únicos.

Não me parece que haja uma ordem como essa, pelo que consigo perceber, então há outra maneira de fazer isto?

o que tenho de conseguir é listar ficheiros de várias pastas (quer existam ou não, o que faço actualmente com dir). A forma como o script (para a aplicação requerente) funciona usa várias fontes para construir um lista de diretório e, posteriormente, o comando, dependendo se a plataforma é Windows ou UNIX, mas o perigo aqui é que há uma possibilidade de diretórios duplicados na lista e isso alteraria os resultados no final.

a maneira mais fácil de lidar com isto é fazê-lo na fonte, ou seja, o comando original a ser executado. Assim, no Linux, a estrutura de comandos é mais ou menos:

find [dir] [dir] [dir] | grep file_name | sort -u

Fazer o mesmo nas janelas é obviamente mais difícil, dado que:

  • it tem de ser um texto nativo apenas para leitura de comandos/script que usaria na linha de comandos do Windows (cmd.exe)
  • não consigo instalar nada nos anfitriões em que isto seja executado
  • não posso criar ficheiros de texto temporários como parte do processo
Author: delronhubbard, 2014-03-12

3 answers

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
SET "line="
FOR /f "delims=" %%a IN ('sort q22351713.txt') DO (
 IF "!line!" neq "%%a" ECHO(%%a
 set "line=%%a"
)
)>newfile.txt

GOTO :EOF
Usei um ficheiro chamado q22351713.txt para os meus testes. Produz um ficheiro Novo.txt

NÃO à prova de bala

É sempre melhor explicar o que o original faz em vez de assumir que é óbvio.
 0
Author: Magoo, 2014-03-12 12:46:43
Lote sujo é sujo...
%COMSPEC% /d /v:on /c "(SET LASTLINE=) & (FOR /f "usebackq tokens=*" %L IN (`DIR /b /s /-p dir1 dir2 dir3 dir3 dir2 dir1 "dir with space" ^| %SYSTEMROOT%\system32\find.exe /i "search_file_name" ^| %SYSTEMROOT%\system32\sort.exe`) DO @((IF /i NOT "{!LASTLINE!}"=="{%~L}" ECHO %~L) & SET "LASTLINE=%~L"))"
Vamos dividir isto um pouco...

%COMSPEC% /d /v:on /s /c "..." - você queria um único comando, não um lote, e precisávamos de expansão atrasada (/v:on), por isso invocamos uma subtileza usando o executável conhecido da linha de comandos Windows (%COMSPEC%). Não queremos executar autoexec.bat (/d) e queremos executar o comando e seguir em frente, em vez de deixar uma shell interactiva (/c "..."). Citando é um problema funky, então nós tentamos para algum comportamento "padronizado" (/s)

SET LASTLINE= - esvaziar qualquer conteúdo actual de uma variável de ambiente LASTLINE

(...) & (...) - execute tudo antes de & e tudo depois de & independentemente do código de saída da primeira parte. Usar parêntesis conforme apropriado para agrupar comandos, quando necessário.

FOR /f "usebackq tokens=*" %L IN (`...`) DO ... - execute a cadeia de comandos entre as fichas (usebackq) e leia todas as palavras (tokens=*) em cada linha de stdout (FOR /f) numa variável temporária %L.

DIR /b /s /-p dir1 dir2 dir3 dir3 dir2 dir1 "dir with space" - enumerar recursivamente (/s através dir1, dir2, dir3 e dir with space, imprimindo apenas o caminho completo dos ficheiros para o stdout (/b). Não necessite de teclas para page o resultado, se este tiver sido definido (/-p). Note que, devido a foibles de FOR, depende de si apenas pastas de aspas com caracteres especiais (por exemplo, espaço), ou seja, não cite nomes de uma única palavra.

... ^| ... - encaminhe o stdout do primeiro comando para o stdin do segundo. Nós usamos ^ para escapar | dentro dos backquotes de FOR.

%SYSTEMROOT%\system32\find.exe /i "search_file_name" - encontre o texto search_file_name em stdin. Usar uma pesquisa sem distinção de maiúsculas (/i).

%SYSTEMROOT%\system32\sort.exe - separem o stdin e escrevam ao stdout.

DO @(...) - temos de executar dois comandos para cada linha, por isso agrupamo-los entre parêntesis. {[25] } normalmente imprime cada comando antes de o executar, o @ suprime isto.

(IF /i NOT "{!LASTLINE!}"=="{%~L}" ECHO %~L) - Se a linha que estamos olhando %~L não é a mesma que a linha que armazenamos !LASTLINE!, imprima a linha que estamos olhando. Mais uma vez, use um comparação insensível à capitalização (/i). Reservamos ambas as variáveis com {} para lidar com valores vazios, e usamos expansão retardada (!LASTLINE! em vez de %LASTLINE%) para expandir LASTLINE cada vez que ele faz loops, não apenas quando o comando FOR é visto pela primeira vez.

SET "LASTLINE=%~L" - armazenar a linha que estamos olhando %~L na variável LASTLINE.

Se não tiver acesso às variáveis de ambiente incorporadas, pode não ter %SYSTEMROOT% ou %COMSPEC%. Substituir estes por C:\Windows e C:\Windows\System32\cmd.exe ou mais apropriadamente, determine os locais corretos para o sistema que você está digitalizando.

 0
Author: jimbobmcgee, 2017-08-17 14:20:24
  1. A Microsoft adicionou uma opção /unique para sort.exe no Windows 10, mas esqueceu-se de actualizar a sua documentação. Testei este interruptor no Windows 7, no Windows 8.1 e no Windows 10 v1709. Estava presente no último, mas ausente dos dois primeiros.

    So, sort.exe /unique is the equivalent of UNIX sort -u.

  2. O PowerShell já tem um cmdlet Sort-Object que suporta um interruptor -Unique. Melhor ainda, por padrão, PowerShell define a alcunha sort para Sort-Object Assim, | sort -unique é é tudo o que precisas.

 0
Author: , 2018-05-13 10:03:37