Este é um problema do Separador de Campo Interno. Pelo contrário, não é um problema, foi projetado dessa maneira. Ele divide a entrada pelo espaço em branco, assim como nos parâmetros posicionais.
Na página do manual do Bash:
para nome [[ em [ palavra ...]]; ] faça lista ; concluído
A lista de palavras após em é expandida, gerando uma lista de itens. A variável nome é definida para cada elemento desta lista, por sua vez, e lista é executada a cada vez. Se o em palavra é
omitido, o comando for executa lista uma vez para cada parâmetro posicional definido. O status de retorno é o status de saída do último comando que é executado. Se o
a expansão dos itens após em resulta em uma lista vazia, nenhum comando é executado e o status de retorno é 0.
Isso significa que ele expande os resultados da expressão em uma lista de palavras. É aqui que entra o separador de campo interno, $ IFS. Por padrão, o $ IFS é definido para espaços em branco (espaço, tabulação e nova linha). Isso significa que um campo consiste em tudo até (mas não incluindo) esses caracteres de espaço em branco. Como os nomes de arquivos consistem em espaços, eles estão tratando-os como vários campos diferentes e executando o loop uma vez para cada campo. A maneira de corrigir isso é ajustar o valor de $ IFS.
Então, você precisa ajustar o $ IFS para algo diferente do espaço em branco. Usando seu método atual, no entanto, não haveria nenhuma maneira de dizer onde um nome de arquivo termina e o outro começa, a menos que todos tenham extensões de arquivo. Uma maneira mais fácil de fazer isso seria usar o utilitário find
da seguinte forma:
#Save the original IFS
oldifs=$IFS
#Set the new IFS to the ASCII null character \x00
IFS=$(echo -ne "\x00")
files="" #To prevent scoping issues
#Use the find utility to find and print just regular files (not directories),
#and not going further than ~/Downloads (remove '-maxlength 1' to make the
#search fully recursive), then print the filenames in the format
#file1\x00file2\x00file3\x00file4...
#However, since our new IFS is now \x00, the boundary upon which these filenames are
#separated now works as expected
for f in $(find ~/Downloads -maxdepth 1 -type f -print0)
do
files="$files,$f"
done
echo "$files"
#Reset IFS
IFS=$oldifs
Eu também gostaria de salientar que sua declaração ls ~/Downloads | grep -v ^d
provavelmente não faz o que você espera. Parece que você estava tentando filtrar diretórios, mas o que está realmente acontecendo aqui é que ele está filtrando os arquivos que começam com 'd'. Isso ocorre porque você não está usando a forma longa de ls
like ls -l
. ls -l
imprime a saída como:
drwxrwxrw- user group SomeDirectory size date_modified filename
wheras 'ls' imprime apenas os nomes dos arquivos:
SomeDirectory
file1
file2
file3