Qual é a diferença entre ls [13] e ls {1,3}?

11

Eu criei três arquivos no meu diretório usando o comando touch inv{1..3}.txt. Agora eu usei dois comandos e sua saída é praticamente a mesma. Esses dois comandos são ls inv[13].txte ls {1,3}.txt.

Então, como esses dois são diferentes? Como os colchetes são diferentes em comparação com os colchetes? Também estava pesquisando no "linux [..]", mas não consegui encontrar nada, então eu poderia saber como essas coisas são chamadas na terminologia do linux?

obrigado

posixKing
fonte
2
O nome para isso é "expansão do nome do arquivo" ou "globbing".
Byte Commander
Qual destes é expansão ou globbing de nome de arquivo? É o colchete ([..]) ou o suporte de flores ({..})?
precisa saber é o seguinte

Respostas:

14
  • {}é chamado de expansão de chave. Ele tem duas formas: {x..y}e {x,y}, substitua xe ypor qualquer valor alfabético ou numérico.

    Na primeira forma, {x..y}será expandido para todos os valores de xpara y, inclusive. Por exemplo, {2..5}será expandido para 2, 3, 4, 5.

    Na segunda forma explícita, {x,y}será expandido para única x, y. Por exemplo, {2,5}será expandido para 2e 5.

    Se nenhuma expansão for possível, o padrão será tratado literalmente, por exemplo, em {a..3}.

    O importante a ser observado é que a expansão de chaves será realizada (se possível), independentemente de qualquer correspondência de arquivo, enquanto estiver na criação / correspondência de arquivo.

  • []é conhecido como padrão de expansão do nome do caminho (ou globbing). Ao contrário da expansão entre chaves, você só pode usá-lo enquanto estiver combinando nomes de arquivos, ele será tratado literalmente se você o usar durante a criação de arquivos.

    Tem duas formas: [xyz...]e [x-y].

    Na primeira forma, ele corresponderá a qualquer caractere único entre colchetes separadamente, ou seja, cada caractere será tratado individualmente. Assim, para [25].txtele vai corresponder a um arquivo chamado 2.txtou 5.txtdo diretório atual, enquanto que para [245].txtisso irá corresponder a qualquer arquivo chamado 2.txtou 4.txtou 5.txt.

    Na segunda forma, uma expansão de intervalo é feita primeiro antes de corresponder individualmente, se possível, caso contrário, seja tratado literalmente. Portanto [2-5]. txt, corresponderá a qualquer arquivo nomeado 2.txtou 3.txtou 4.txtou 5.txt. Se o intervalo não puder ser expandido, será tratado literalmente, por exemplo, no caso de [a-3].txt.


Uma diferença comportamental importante entre esses dois é quando há mais padrões para corresponder, enquanto menos na verdade é correspondido. Como a expansão de chave é feita, não importa o que aconteça, mostrará o erro de que certos arquivos não existem enquanto a expansão do nome do caminho corresponderá ao possível, sem nenhum erro para o restante:

$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt  2.txt  3.txt

$ ls [1-4].txt
1.txt  2.txt  3.txt

Nota de portabilidade:

O []operador de expansão do nome do caminho é definido pelo POSIX, portanto, portátil entre o shell e os derivados Bourne.

A expansão de brace,, {}não é definida pelo POSIX, portanto, não é portátil entre todos os shells. Por exemplo, dash( shno Ubuntu) não tem isso. Ele foi emprestado cshe vai trabalhar em certas conchas única por exemplo bash, zsh, ksh93, fish. Verifique se o shell que você está usando suporta isso antes da implementação.


Exemplo:

$ touch {1..3}.txt

$ ls {1..3}.txt
1.txt  2.txt  3.txt

$ ls {1,2,3}.txt
1.txt  2.txt  3.txt

$ ls {1..4}.txt
ls: cannot access 4.txt: No such file or directory
1.txt  2.txt  3.txt

$ ls {a..3}.txt
ls: cannot access {a..3}.txt: No such file or directory

$ ls [123].txt
1.txt  2.txt  3.txt

$ ls [1-3].txt
1.txt  2.txt  3.txt

$ ls [1-4].txt
1.txt  2.txt  3.txt

$ ls [a-3].txt
ls: cannot access [a-3].txt: No such file or directory
heemail
fonte
1
Deve-se evitar confiar no comportamento da [ ]expansão quando não houver correspondências, pois isso pode ser diferente dependendo da configuração do shell. Se você deseja usar [ou ]em um nome de arquivo, ele deve ser citado em seus comandos. Também vale a pena notar a diferença entre {13..79}e [13-79]. O primeiro irá produzir todos os números na faixa de 13a 79, o segundo irá coincidir com os personagens 1, 3, 4, 5, 6, 7, e 9.
kasperd
@ Kasperd Sim, é para isso que serve nullglob(ou similar). Sobre a [13-79]correspondência, acho que mencionei claramente na minha resposta sobre o comportamento por caractere de [] `.
heemayl
@heemayl Acho que também vale a pena mencionar que a forma `{1..3}` é o basismo. Isso não vai funcionar bem. Eu acho que kshtem esse recurso, mas não é sabores mais modernos, como mksh e pkdsh
Sergiy Kolodyazhnyy
@Serg Adicionada a nota de portabilidade.
heemayl 3/09/16
7

A principal diferença entre as duas formas é ilustrada aqui:

$ ls inv[15].txt
inv1.txt
$ ls inv{1,5}.txt
ls: cannot access 'inv5.txt': No such file or directory
inv1.txt

inv[15].txté um glob e expandirá a lista de arquivos correspondentes em seu sistema de arquivos. Essa é a expansão do nome do caminho .

inv{1,5}.txtexpande para inv1.txte inv5.txtindependentemente de quais arquivos estão realmente no seu sistema de arquivos. Isso é expansão de chaves .

John1024
fonte
A outra diferença principal é que você pode escrever ba{con,tman}e não há equivalente usando colchetes. IOW, a expansão de chaves não é apenas para caracteres únicos.
hobbs