Expansão pelo shell
As aspas em torno de "$i*.csv" fazem a diferença. Com as aspas, o shell expande essa string para "2014-11 / *. Csv". Esse arquivo exato não existe e zip relata um erro. Sem aspas, o * também se expande (via expansão de nome de arquivo / "globbing"), e o comando zip resultante é uma lista completa de arquivos correspondentes, cada um como um argumento separado. Você pode obter o segundo comportamento, dentro do for loop, com:
for i in */ ; do zip "zips/${i%/}.zip" "$i"*.csv ; done
Expansão por zip
zip também pode expandir curingas para si mesmo, mas não em todas as situações. Do manual do zip :
The zip program can do the same matching on names that are in the zip archive being modified or, in the case of the -x (exclude) or -i (include) options, on the list of files to be operated on, by using backslashes or quotes to tell the shell not to do the name expansion.
O comando original funciona em tentativas subsequentes, depois de você ter criado um arquivo com êxito, porque zip tenta corresponder os curingas ao conteúdo do arquivo existente. Eles existem lá e ainda existem no sistema de arquivos, então eles são reportados com updating: .
Para obter zip para manipular os curingas quando criar o arquivo morto, use a opção -r (recurse) para recursar no diretório solicitado e -i (include) para limitá-lo para arquivos que correspondem ao padrão:
for i in */ ; do zip -r "zips/${i%/}.zip" "$i" -i '*.csv' ; done