AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / ubuntu / Perguntas / 1518193
Accepted
stackbiz
stackbiz
Asked: 2024-06-20 21:06:03 +0800 CST2024-06-20 21:06:03 +0800 CST 2024-06-20 21:06:03 +0800 CST

Como usar o asterisco (*) no array bash

  • 772

Quero armazenar tudo command argsem um array, mas só funciona quando todos os argumentos não possuem nenhum ( *).

Aqui está um teste sem usar array:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt

mkdir -p /tmp/world

# This cp command is success
cp /tmp/hello/* /tmp/world

Agora converta o comando cp em my_array:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt

mkdir -p /tmp/world

declare -a my_array=()
my_array[0]="cp"
my_array[1]="/tmp/hello/*"
my_array[2]="/tmp/world"

# Run the command and it will fail
"${my_array[@]}"

Aqui está o erro:

cp: cannot stat '/tmp/hello/*': No such file or directory

É possível usar ( *) no my_array? Qual é a sintaxe correta para implementar o ' cp /tmp/hello/* /tmp/world' with my_array?

Atualizar:

Existe um problemfrom @choroba's answoer, The $counte $sedond_itemestará errado:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt

mkdir -p /tmp/world

my_array=(cp)
my_array+=(/tmp/hello/*)
my_array+=(/tmp/world)

count=${#my_array[@]}
printf "%s\n" "count is: $count"

sedond_item="${my_array[1]}"
printf "%s\n" "second item is: $sedond_item"

Aqui está o resultado da resposta de @choroba:

count is: 4
second item is: /tmp/hello/hello.txt

Mas os $counte $sedond_itemestão corretos no meu array original:

mkdir -p /tmp/hello
echo "hello" > /tmp/hello/hello.txt
echo "world" > /tmp/hello/world.txt

mkdir -p /tmp/world

declare -a my_array=()
my_array[0]="cp"
my_array[1]="/tmp/hello/*"
my_array[2]="/tmp/world"

count=${#my_array[@]}
printf "%s\n" "count is: $count"

sedond_item="${my_array[1]}"
printf "%s\n" "second item is: $sedond_item"

Aqui está a saída do array original:

count is: 3
second item is: /tmp/hello/*
command-line
  • 2 2 respostas
  • 119 Views

2 respostas

  • Voted
  1. Best Answer
    steeldriver
    2024-06-21T01:53:37+08:002024-06-21T01:53:37+08:00

    Eu não acho que você possa - com segurança 1 - fazer o que quiser no bash.

    No bash (assim como no POSIX sh e ksh), aspas duplas de expansões de parâmetros (incluindo expansões de array como "{my_array[@]}"em shells que as suportam) evitam a divisão de palavras e a geração de nomes de arquivos (também conhecidos como globbing). Por outro lado, expansões sem aspas estão sujeitas tanto à divisão quanto ao globbing de palavras (a chamada operação "split+glob"). No bash, você pode desativar o globbing usando set -f(ou equivalente set -o noglob), mas no AFAIK você não pode desativar a divisão de palavras enquanto deixa o globbing ativado .

    Observe que a divisão de palavras ocorre antes do globbing, portanto, não é a expansão de /path/without/whitespace/*to /path/without/whitespace/name with whitespaceque é o problema - é a expansão de /path with whitespace/*.

    No entanto, no zsh, as expansões de variáveis ​​​​sem aspas não estão sujeitas a split+glob por padrão, e você pode ativar o globbing separadamente usando o ~parâmetro expansion flag 2 .

    Observe que em todos os casos, o RHS de uma atribuição como var=*ou my_array[1]=/tmp/hello/*não é expandido mesmo quando não está entre aspas.

    Assim, em zsh, por exemplo (observando que as matrizes zsh são indexadas de 1 e não de 0 como no bash):

     % typeset -a my_array
     % my_array[1]=ls
     % my_array[2]="my dir/*"
     % typeset -p my_array
    typeset -a my_array=( ls 'my dir/*' )
    
     % ${my_array[@]}
    ls: cannot access 'my dir/*': No such file or directory
    

    (o mesmo que citado "${my_array[@]}"em bash e zsh), mas

     % ${~my_array[@]}
    'my dir/hello'  'my dir/world'
    

    Você pode verificar se o globbing está acontecendo no momento da expansão adicionando outro arquivo:

     % touch 'my dir/a new file'
    steeldriver@steeldriver-virtualbox ~/dir
     % ${~my_array[@]}          
    'my dir/a new file'  'my dir/hello'  'my dir/world'
    

    Para o seu caso específico eu sugiro adicionar algumas medidas de segurança - em particular usar GNU mv's -tpara definir explicitamente o diretório de destino e -nevitar sobrescrições acidentais, e um argumento adicional --para marcar o fim das opções (o que se torna importante se o globo puder se expandir para nomes de arquivos começando com hífens):

    #!/bin/zsh
    
    typeset -a my_array
    
    my_array[1]=mv
    my_array[2]=-nt
    my_array[3]=/tmp/world
    my_array[4]=--
    my_array[5]=/tmp/hello/*
    
    ${~my_array[@]}
    

    Embora TBH, se você for mudar para zsh, considere usar o zmvmódulo contribuído - que pega expressões glob (entre aspas) e as expande internamente - no lugar de plain mv.


    1. com o que quero dizer sem usareval

    2. embora observe que ${~my_array[@]}o globbing é ativado durante a expansão de cada elemento da matriz

    • 2
  2. choroba
    2024-06-20T21:23:03+08:002024-06-20T21:23:03+08:00

    Use o asterisco ao preencher o array, mas não preencha um elemento por vez:

    my_array=(cp /tmp/hello/* /tmp/world)
    "${my_array[@]}"
    

    Ou use o +=operador para expandir o array:

    my_array=(cp)
    my_array+=(/tmp/hello/*)
    my_array+=(/tmp/world)
    "${my_array[@]}"
    
    • 1

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Existe um comando para listar todos os usuários? Também para adicionar, excluir, modificar usuários, no terminal?

    • 9 respostas
  • Marko Smith

    Como excluir um diretório não vazio no Terminal?

    • 4 respostas
  • Marko Smith

    Como descompactar um arquivo zip do Terminal?

    • 9 respostas
  • Marko Smith

    Como instalo um arquivo .deb por meio da linha de comando?

    • 11 respostas
  • Marko Smith

    Como instalo um arquivo .tar.gz (ou .tar.bz2)?

    • 14 respostas
  • Marko Smith

    Como listar todos os pacotes instalados

    • 24 respostas
  • Martin Hope
    Flimm Como posso usar o docker sem sudo? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    led-Zepp Como faço para salvar a saída do terminal em um arquivo? 2014-02-15 11:49:07 +0800 CST
  • Martin Hope
    ubuntu-nerd Como descompactar um arquivo zip do Terminal? 2011-12-11 20:37:54 +0800 CST
  • Martin Hope
    TheXed Como instalo um arquivo .deb por meio da linha de comando? 2011-05-07 09:40:28 +0800 CST
  • Martin Hope
    Ivan Como listar todos os pacotes instalados 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    David Barry Como determino o tamanho total de um diretório (pasta) na linha de comando? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher "Os seguintes pacotes foram retidos:" Por que e como resolvo isso? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford Como os PPAs podem ser removidos? 2010-07-30 01:09:42 +0800 CST

Hot tag

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve