mv: Can't stat Não existe esse arquivo ou diretório no shell script


16

Escrevi um script para mover alguns arquivos de uma pasta para outra, mas recebi o seguinte erro, verifiquei 2 pastas e observe que em uma pasta existem esses arquivos e em outro não, mas por que todos eles mostram "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 /home/esolve/project/capture/tcp_50x50/


1
Por favor, mostre as partes relevantes do script.
24513 Mat

Atualizei minha pergunta e adicionei o script, obrigado!
misteryes

Você precisa adicionar um -rao mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}?
ProfessionalAmateur

não há -ropção paramv
misteryes

Respostas:


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

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

Mude para:

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

(Aspas duplas para evitar problemas se você 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 argumento para o comando.)


As aspas duplas fazem sentido, mas por que preciso colocar *fora das aspas?
Sibbs Gambling

Se você quiser se expandiu, você precisa dele @SibbsGambling fora
Mat

8

Existem vários problemas com o seu código:

list=`ls dest_folder`

Você está armazenando a saída lssem os caracteres de nova linha à direita $list. lsgera 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, para que a saída não possa ser usada com confiabilidade. Por exemplo, a lssaída para um diretório que contém ae bé igual à de 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 verdade cd, porque o restante dos comandos assume que você está nesse novo diretório e que pode ter consequências dramáticas quando não estiver.

cwd=`pwd`

Os shells POSIX já mantêm o (um) caminho para o diretório atual na $PWDvariável, portanto você não precisa usá-lo pwdaqui (especialmente no caso geral, pois a substituição de comandos remove os caracteres de nova linha à direita do caminho). Além disso, mvaceita 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 em shells. Ou seja, o conteúdo da variável é dividido (nos separadores mencionados em $IFScom 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 arquivos correspondentes.

Aqui, você deseja a divisão, mas apenas em caracteres de nova linha, e não deseja o globbing, portanto, será necessário desativá-lo:

 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 nenhum, então você precisa citar essas variáveis.

Como já mencionado, os curingas são expandidos apenas quando não estão entre aspas; é necessário removê- *lo das aspas. Se você desativou o globbing anteriormente set -f, precisará restaurá-lo set +fantes 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 datapastas.
  • Não estamos verificando a substituição de arquivos no processo (você pode adicionar a -iopção mv).
  • Ao usar */, estamos repetindo apenas os diretórios , mas isso inclui links simbólicos para os diretórios também. Se preferir, adicione um [ -L "${folder%/}" ] && continuedentro do loop.
  • Se não houver uma pasta não oculta, ela */se expandirá para si mesma; assim, você receberá uma mensagem de erro mvdizendo que não consegue encontrar um arquivo chamado */data/*. Da mesma forma, se não houver arquivo não oculto em nenhuma das pastas, você receberá uma mensagem de erro que that-folder/data/*não existe.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.