mv: cannot stat Nenhum arquivo ou diretório no script de shell

9

Eu escrevi um script para mover alguns arquivos de uma pasta para outra mas eu tenho o seguinte erro, eu verifiquei 2 pastas e aviso para 1 pasta existem tais arquivos e outro não há tais arquivos, mas porque todos eles mostra "mv não pode stat Nenhum desses arquivos ou diretório"

    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/194.42.17.124_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/195.113.161.13_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/212.199.61.205_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/212.51.218.235_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/213.73.40.105_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/41.225.7.4_tcp.folder/data/*': No such file or directory
    mv: cannot stat '/home/esolve/project/capture/tcp_50x50/dest_folder/83.230.127.122_tcp.folder/data/*': No such file or directory
    [esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/
    [esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/
    129.88.70.226   132.187.230.1    138.96.116.22   155.185.54.250   192.38.109.144  193.136.227.163  193.175.135.61  195.113.161.13  83.230.127.122
    130.104.72.200  132.227.62.122   147.83.29.232   156.17.10.52     192.42.43.22    193.137.173.218  193.205.215.74  212.199.61.205
    131.130.69.164  132.252.152.194  148.81.140.193  157.181.175.249  192.43.193.71   193.144.21.131   193.226.19.30   212.51.218.235
    131.188.44.102  134.151.255.180  152.66.245.162  160.78.253.31    193.1.170.136   193.145.46.243   194.199.68.165  213.73.40.105
    131.254.208.10  138.48.3.203     152.81.47.4     192.114.4.3      193.136.166.56  193.166.160.98   194.42.17.124   41.225.7.4

o script é:

    list='ls dest_folder'
    cd dest_folder
    cwd='pwd'
    for folder in $list;do
            mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
    done

Eu corri em /home/esolve/project/capture/tcp_50x50/

    
por misteryes 24.05.2013 / 21:09

2 respostas

14
mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

As aspas ( ' ) impedem que o shell faça globbing. O * está sendo passado literalmente para o comando mv , que falha, pois não encontra arquivos chamados * nos diretórios indicados.

Altere isso para:

mv "${cwd}/${folder}/data"/* "${cwd}/${folder}"

(Aspas duplas para evitar problemas se você já tiver um nome de diretório com espaços. * fora das aspas.)

Você ainda receberá os erros dos diretórios vazios. (O mesmo tipo de razão: se o arquivo não encontrar uma correspondência para o padrão, ele passará o próprio padrão como um argumento para o comando).

    
por 24.05.2013 / 22:02
7

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.
por 25.05.2013 / 08:40

Tags