Eu tenho a seguinte estrutura de arquivos:
- /home/dados/C01/dir_wwe_346/arquivo1.txt pic.jpg random.sh
- /home/dados/C02/dir_wwe_644/arquivo1.txt pic.jpg random.sh
- /home/dados/C03/dir_wwe_324/arquivo1.txt pic.jpg random.sh
Eu quero que eles sejam assim:
- home/data/C01/file1.txt pic.jpg random.sh
- home/data/C02/file1.txt pic.jpg random.sh
- home/data/C03/file1.txt pic.jpg random.sh
Basicamente, é mover vários arquivos para um diretório acima. Tentei este script sem sucesso:
#!/bin/bash for i in */ do cd i/*/ mv * ../ done
Depois de postar isso (mas antes de ler a resposta do grawity abaixo), percebi que não usei a expansão de variável adequada e executei isto:
#!/bin/bash for i in */ do cd ${i}*wwe* mv * ../ done
O script está movendo todos os subdiretórios para a pasta de dados, então estou terminando com isto:
- /lar/C01/dir_wwe_346/arquivo1.txt pic.jpg random.sh
- /lar/C02/dir_wwe_644/arquivo1.txt pic.jpg random.sh
/lar/C03/dir_wwe_324/arquivo1.txt pic.jpg random.sh
O que estou fazendo de errado?
PS. Editei a postagem para que revele o processo pelo qual passei e para que as respostas façam mais sentido para os recém-chegados que possam se beneficiar com elas. Obrigado grawity, aprendi algo novo. Comecei a aprender bash há uma semana e sinto que estou progredindo.
Responder1
As variáveis só são reconhecidas e expandidas com o
$
prefixo. Se o loop definir uma variável 'i', você precisará usar$i
sempre que você quiser seu valor:for i in */; do cd $i/*/
O "diretório atual" abrange todo o processo e não redefine automaticamente cada iteração do loop. Você precisa retornar manualmente ao diretório pai posteriormente:
cd $i/*/; mv * ../; cd ../../
ou use um "subshell" para definir o escopo da alteração do diretório:
(cd $i/*/; mv * ../)
Você não está fazendo nenhuma verificação de erros. Se
cd
alguma vez falhar, o subsequentemv
poderá fazer coisas desagradáveis. Junte os comandos usando&&
ou faça a verificação oposta e use|| exit
(ou|| break
), o que parecer melhor:for i in */; do cd $i/*/ && { mv * ../; cd ../../ } done for i in */; do cd $i/*/ || exit mv * ../ cd ../../ done for i in */; do (cd $i/*/ && mv * ../) done
Melhoria: você pode mover o curinga do subdiretório para
mv
, permitindo que funcione mesmo no caso de haver vários subdiretórios:cd $i/ || exit mv */* . cd ../
Melhoria: você poderia fazer isso sem precisar
cd
de nada:mv $i/*/* $i/