Existem vários problemas com o seu código:
list='ls dest_folder'
Você está armazenando a saída de ls
sem os caracteres de nova linha à direita em $list
. ls
exibe a lista de nomes de arquivos separados por caracteres de nova linha. newline
é um caractere tão válido quanto qualquer outro em um nome de arquivo, portanto, a saída não pode ser usada de maneira confiável. Por exemplo, a saída ls
para um diretório que contém a
e b
é a mesma que para um diretório que contém um arquivo chamado a<newline>b
.
cd dest_folder
Você não está verificando a falha desse comando. Em geral, você deve verificar o status de saída dos comandos, mas isso é especialmente verdadeiro de cd
, porque o restante dos comandos presumem que você está nesse novo diretório e isso pode ter consequências dramáticas quando você não está.
cwd='pwd'
POSIX shells já mantêm o (um) caminho para o diretório atual na variável $PWD
, então você não deve precisar usar pwd
aqui (especialmente no caso geral, já que a substituição de comandos removeria arrastando caracteres de nova linha a partir do caminho). Além disso, mv
aceita caminhos relativos para que você não precise criar o caminho absoluto.
for folder in $list;do
Deixar uma variável sem aspas é o operador split + glob nos shells. Ou seja, o conteúdo da variável é dividido (nos separadores mencionados em $IFS
com regras especiais para os espaços em branco), e cada elemento resultante dessa divisão é procurado por caracteres curinga para que possam ser expandidos para a lista de correspondência arquivos.
Aqui, você quer a divisão, mas apenas em caracteres de nova linha, e você não quer a globulação, então você precisa desativá-la:
IFS='
'; set -f
for folder in $list
mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
Novamente, deixar uma variável sem aspas é o operador split + glob . Aqui, você não quer nem, então você precisa citar essas variáveis.
Como já foi mencionado, os curingas são expandidos apenas quando não citados, para que você precise mover *
das cotações. Se você tiver desativado a globulação anteriormente com set -f
, será necessário restabelecê-lo com set +f
antes de chamar esse comando.
Uma maneira muito melhor de escrever seria:
cd dest_folder &&
for folder in */;do
mv -- "${folder}data/"* "$folder"
done
Algumas notas:
- Isso excluirá pastas ocultas e não moverá arquivos ocultos das pastas
data
.
- Não estamos verificando se os arquivos estão sendo substituídos no processo (talvez você queira adicionar a opção
-i
a mv
).
- Usando
*/
, estamos passando por diretórios apenas, mas isso também inclui links simbólicos para diretórios. Se preferir, você precisará adicionar um [ -L "${folder%/}" ] && continue
dentro do loop.
- Se não houver nenhuma pasta não oculta,
*/
será expandido para si mesmo, então você receberá uma mensagem de erro de mv
dizendo que não é possível encontrar um arquivo chamado */data/*
. Da mesma forma, se não houver nenhum arquivo não oculto em nenhuma das pastas, você receberá uma mensagem de erro indicando que that-folder/data/*
não existe.