CMD: *. * Ou apenas *?

47

Nos anos 90, eu usaria " *.*" para representar qualquer nome de arquivo no MS-DOS, mas vi mais scripts usando apenas " *" atualmente. Realmente faz alguma diferença qual deles eu uso?

Foebane
fonte
9
Embora seja verdade que *e *.*agora são equivalentes para cmdcomandos internos e utilitários de linha de comando modernos, alguns utilitários mais velhos que usam parâmetros de máscara de arquivo podem usar as funções correspondentes arquivo mais velhos, e para eles as máscaras não será equivalente.
AFH 03/07
@ AFF Não acho que os tokens sejam iguais. O *.*token não deve retornar arquivos sem extensão.
Tuskiomi 11/07
11
@ tuskiomi - Eu concordo com você que *.* não deve retornar arquivos sem extensão. Infelizmente sim. Veja a resposta do Grawity.
AFH 11/07

Respostas:

65

O nome e a extensão do arquivo têm sido um campo único desde que o Windows 95 e o NT 3.5 introduziram o suporte ao "nome longo do arquivo", e as correspondências curinga são feitas no nome do arquivo inteiro de uma só vez. Como resultado, você pode ter um nome de arquivo sem pontos (talvez raro para arquivos, mas muito comum para pastas / diretórios) e, à primeira vista *.*, não corresponda a esses arquivos.

Scripts antigos usando *.* irá ainda trabalho por causa do código de compatibilidade - se as extremidades curinga com .*, essa parte é ignorada pelo sistema operacional. (Portanto, se você deseja corresponder especificamente arquivos com uma extensão, acho que precisaria *.?*disso.)

Mas não é algo em que você deva confiar; se você estiver escrevendo scripts para versões modernas do Windows, siga as convenções, não as convenções do MS-DOS. (Observe que, no Windows NT, os scripts .bat não são mais interpretados pelo MS-DOS, mas por cmd.exeum programa Win32 nativo.)


No Linux e em vários outros Unixen, nome e extensão nunca foram separados em primeiro lugar, e não mágica especial para fazer o *.*trabalho, por isso *é a única opção que faz sentido.

gravidade
fonte
14
"Vamos tornar mais difícil filtrar arquivos com extensões! Yay!" -Anônimo Microsoft Developer
John Hamilton
50
"Vamos quebrar os milhões de scripts em lote existentes para todos! Yay!" -No Microsoft Developer, Ever
grawity
3
ISTR que, em algumas versões antigas do DOS, *corresponderia apenas aos nomes de arquivos sem uma extensão. A maneira 'segura' de ser compatível com ambos era usar **.
precisa saber é o seguinte
8
O OP é sobre o Windows, mas desde que você mencionou o Linux: em alguns shells (Bash, por exemplo), *( por padrão ) não corresponde aos nomes de arquivos ocultos (começando com a .).
Florian Brucker
4
Para alguns valores de "nível de SO" ... Na verdade, também é um conceito de shell (Explorer) no Windows - o kernel não se importa com .exe nos executáveis, nem em nada mais. Se o Windows Explorer tem mais "nível de SO" do que, por exemplo, o Nautilus no Linux, pode ser discutido.
grawity
11

É provavelmente vale a pena mencionar que o UNIXy / conchas posixy como shell Bourne, bash, ksh, zsh, etc fazer expansão curinga (de caracteres glob como *, ?, [range], [!range]e outras expansões como chaves e globs estendidos) para compilar uma lista de argumentos antes de o comando É executado. Portanto, essa expansão é feita pelo shell e não pelo comando ao qual esses argumentos podem ser discutidos.

ou seja, o shell é responsável pelo quê *, *.*expande para

 $ ls
 file.csv  file.doc  file.pdf  file.txt  file.xlsx  zz-file-without-extension

 $ (set -xv; foo *)   # is actually expanded to the following
   + foo file.csv file.doc file.pdf file.txt file.xlsx zz-file-without-extension

 $ (set -xv; foo *.*)  # note this does not match `zz-file-without-extension`
   + foo file.csv file.doc file.pdf file.txt file.xlsx

Esse não é o caso no CMD (e da mesma forma para os utilitários do PowerShell ), pois ele passa os caracteres glob literalmente para o comando executado - e, portanto, a expansão é de responsabilidade do comando / utilitário e não do shell. Então, em última análise, o que *.*ou o *meio é deixado para o utilitário, deixando-o em conformidade (ou não) com as convenções - e é por isso que os utilitários do CMD dir *.*também combinam (sem dúvida incorretamente, mas preservam as expectativas) os arquivos sem extensões.

Eu acredito que é seguro resumir dessa maneira.

  • Sob o CMD, isso depende do utilitário.
  • No PowerShell, os utilitários que fazem uso da classe WildCardPattern fornecerão um subconjunto consistente de comportamentos posixy.
shalomb
fonte
Outra diferença é que, no CMD, a maioria dos programas realmente encaminha o curinga bruto para o kernel (FindFirstFile), enquanto o glob no Linux apenas pega a lista completa e faz a filtragem no espaço do usuário.
grawity
Quando você executa * em um diretório com um milhão de arquivos, o comando reclama de muitos parâmetros. Na pior das hipóteses, poderia silenciosamente soltar o final da lista. Nesses casos, você precisa canalizar dois ou mais comandos ou salvar uma lista de nomes de arquivos em um arquivo, para que outro processo possa ler a lista.
Enric Naval
3
@grawity Para ser mais preciso, a filtragem é feita pelo driver do sistema de arquivos no Windows. Isso é especialmente útil em sistemas de arquivos de rede (especialmente quando você pode estar executando uma linha de 8 kb em um sistema de arquivos remoto), mas também significa que você não pode fazer pesquisas arbitrárias nem pesquisas explicitamente suportadas. As implicações disso foram exploradas muitas vezes no blog de Raymond Chen. FindFirstFileem si é o modo de usuário (o kernel32.dll e o ntdll.dll são bibliotecas no modo de usuário - faz parte do subsistema Win32, não do kernel), mas na verdade não faz muito.
Luaan 04/07/19
Ah, eu tive a impressão de que o FindFirstFile envolveu diretamente um syscall de nome semelhante (como o open (3) na libc apenas envolve o open (2) no kernel do Linux).
grawity
11
@cup: Basta usar aspas para impedir que o shell expanda os globs, para que você possa passá-los para os comandos. por exemplo mmv "fred.*" "tom.#1". (A substituição usa em #1vez de *, o que tem a vantagem de permitir que você reordene os campos). mmvnão é instalado por padrão na maioria dos sistemas, mas outras ferramentas de renomeação em lote geralmente são. Consulte este artigo e stackoverflow.com/questions/417916/how-to-do-a-mass-rename .
Peter Cordes