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.