Estou tentando construir uma matriz em bash dos nomes de arquivos da minha câmera:
FILES=(2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg)
Como você pode ver, há um espaço no meio de cada nome de arquivo.
Tentei colocar cada nome entre aspas e escapar do espaço com uma barra invertida, nenhuma das quais funciona.
Quando tento acessar os elementos da matriz, ele continua tratando o espaço como o elemento delimitador.
Como capturar corretamente os nomes de arquivos com um espaço dentro do nome?
FILES[0] = ...
? (Edit: Acabei de fazer; não funciona. Interessante).find . -maxdepth 1 -type f -iname \*.$1 -printf '%f\n'
); para o elemento em $ {array [@]}; faça eco do elemento $; feitoRespostas:
Acho que o problema pode estar em parte na maneira como você está acessando os elementos. Se eu fizer um simples
for elem in $FILES
, encontro o mesmo problema que você. No entanto, se eu acessar a matriz por meio de seus índices, assim funcionará se eu adicionar os elementos numericamente ou com escapes:Qualquer uma dessas declarações de
$FILES
deve funcionar:ou
ou
fonte
echo "${FILES[$i]}"
). Não importaecho
, mas será útil para qualquer coisa que o use como nome de arquivo.for f in "${FILES[@]}"
.#
símbolo sharp ( ) faz nafor ((i = 0; i < ${#FILES[@]}; i++))
declaração?Deve haver algo errado com a maneira como você acessa os itens da matriz. Veja como é feito:
Na página de manual do bash :
Obviamente, você também deve usar aspas duplas ao acessar um único membro
fonte
expands to a single word with the value of each array member separated by the first character of the IFS special variable
for elem in "${files[@]}"
enquanto eles têmfor elem in ${files[@]}
- então os espaços confundem a expansão e as tentativas de execução nas palavras individuais.Você precisa usar o IFS para parar o espaço como delimitador de elemento.
Se você deseja separar com base em. então faça IFS = "." Espero que ajude você :)
fonte
IFS=""
antes da construção da matriz .Concordo com os outros que é provável que você esteja acessando os elementos que são o problema. A citação dos nomes de arquivo na atribuição da matriz está correta:
O uso de aspas duplas em torno de qualquer matriz do formulário
"${FILES[@]}"
divide a matriz em uma palavra por elemento da matriz. Não faz nenhuma divisão de palavras além disso.Usar
"${FILES[*]}"
também tem um significado especial, mas une os elementos da matriz ao primeiro caractere de $ IFS, resultando em uma palavra, que provavelmente não é o que você deseja.Usando um valor simples
${array[@]}
ou${array[*]}
assuntos, o resultado dessa expansão para uma maior divisão de palavras, resultará em palavras divididas em espaços (e qualquer outra coisa dentro$IFS
) em vez de uma palavra por elemento da matriz.Usar um loop for no estilo C também é bom e evita a preocupação com a divisão de palavras, se você não estiver claro:
fonte
Escapar funciona.
Resultado:
Citar as strings também produz a mesma saída.
fonte
Se você tivesse seu array assim: #! / Bin / bash
Você obteria:
Não sei por que, mas o loop divide os espaços e os coloca como um item individual, até você o envolve com aspas.
Para contornar isso, em vez de chamar os elementos da matriz, você chama os índices, que recebem a cadeia completa envolvida entre aspas. Deve estar entre aspas!
Então você terá:
fonte
Não é exatamente uma resposta para o problema de citação / escape da pergunta original, mas provavelmente algo que realmente teria sido mais útil para o op:
Onde é claro que a expressão teria que ser adotada para o requisito específico (por exemplo,
*.jpg
para todas ou2001-09-11*.jpg
apenas as figuras de um determinado dia).fonte
Outra solução é usar um loop "while" em vez de um loop "for":
fonte
Se você não está preso ao uso
bash
, o manuseio diferente dos espaços nos nomes dos arquivos é um dos benefícios da casca do peixe . Considere um diretório que contém dois arquivos: "a b.txt" e "b c.txt". Aqui está um palpite razoável ao processar uma lista de arquivos gerados a partir de outro comandobash
, mas falha devido aos espaços nos nomes dos arquivos que você encontrou:Com
fish
, a sintaxe é quase idêntica, mas o resultado é o que você esperaria:Funciona de maneira diferente porque o peixe divide a saída dos comandos em novas linhas, não em espaços.
Se você tem um caso em que deseja dividir espaços em vez de novas linhas,
fish
há uma sintaxe muito legível para isso:fonte
Eu costumava redefinir o valor e a reversão do IFS quando concluído.
Possível saída do loop:
fonte