mv: no puede stat No existe tal archivo o directorio en el script de shell

16

Escribí una secuencia de comandos para mover algunos archivos de una carpeta a otra, pero recibí el siguiente error, verifiqué 2 carpetas y noté que en 1 carpeta hay dichos archivos y en el otro no, pero por qué todos muestran "mv no puede stat No tales archivos o directorio "

    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

el guión es:

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

Lo corrí en /home/esolve/project/capture/tcp_50x50/

misteryes
fuente
1
Muestre las partes relevantes del guión.
Mat
Actualicé mi pregunta y agregué el script, ¡gracias!
misteryes
¿Necesita agregar un -ra la mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}?
ProfessionalAmateur
no hay -ropción paramv
misteryes

Respuestas:

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

Las comillas ( ') allí evitan que el shell haga globbing. El *se pasa literalmente al mvcomando, que falla ya que no encuentra los archivos llamados *en los directorios indicados.

Cambia esto a:

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

(Comillas dobles para evitar problemas si alguna vez tiene un nombre de directorio con espacios. *Fuera de las comillas).

Sin embargo, todavía obtendrá los errores para los directorios vacíos. (El mismo tipo de razón: si el archivo no encuentra una coincidencia para el patrón, pasa el patrón en sí mismo como un argumento para el comando).

Estera
fuente
Las comillas dobles tienen sentido, pero ¿por qué necesito poner *fuera de las comillas?
Sibbs Gambling
Si quiere expandirlo, lo necesita fuera de @SibbsGambling
Mat
8

Hay varios problemas con su código:

list=`ls dest_folder`

Estás almacenando la salida de lssin los caracteres de nueva línea al final $list. lsgenera la lista de nombres de archivo separados con caracteres de nueva línea. newlinees un carácter tan válido como cualquiera en un nombre de archivo, por lo que la salida no se puede usar de manera confiable. Por ejemplo, el lsresultado de un directorio que contiene ay bes el mismo que el de un directorio que contiene un archivo llamado a<newline>b.

 cd dest_folder

No está comprobando el fallo de ese comando. En general, debe verificar el estado de salida de los comandos, pero eso es especialmente cierto cd, porque el resto de los comandos asumen que está en ese nuevo directorio, y eso podría tener consecuencias dramáticas cuando no lo esté.

cwd=`pwd`

Los shells POSIX ya mantienen la (una) ruta al directorio actual en la $PWDvariable, por lo que no debería necesitar usarla pwdaquí (especialmente en el caso general, ya que la sustitución de comandos eliminaría los caracteres de línea nueva de la ruta). Además, mvacepta rutas relativas para que no necesite construir la ruta absoluta.

for folder in $list;do

Dejar una variable sin comillas es el operador split + glob en shells. Es decir, el contenido de la variable se divide (en los separadores mencionados $IFScon reglas especiales para los espacios en blanco), y cada elemento resultante de esa división se busca con caracteres comodín para que puedan expandirse a la lista de archivos coincidentes.

Aquí, sí desea la división, pero solo en los caracteres de nueva línea, y no desea el bloqueo, por lo que deberá deshabilitarlo:

 IFS='
 '; set -f
 for folder in $list
   mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

Nuevamente, dejar una variable sin comillas es el operador split + glob . Aquí, no quiere ninguno, por lo que necesita citar esas variables.

Como ya se mencionó, los comodines solo se expanden cuando no se citan, por lo que debe *eliminarlo de las comillas. Si ha deshabilitado el globbing antes set -f, deberá restablecerlo set +fantes de llamar a ese comando.

Una forma mucho mejor de escribirlo sería:

cd dest_folder &&
  for folder in */;do
    mv -- "${folder}data/"* "$folder"
  done

Algunas notas sin embargo:

  • Eso excluirá las carpetas ocultas y no moverá los archivos ocultos de las datacarpetas.
  • No estamos verificando si los archivos se anulan en el proceso (es posible que desee agregar la -iopción mv).
  • Al usarlo */, estamos recorriendo solo directorios , pero eso también incluye enlaces simbólicos a directorios. Si prefiere no hacerlo, deberá agregar un [ -L "${folder%/}" ] && continuedentro del bucle.
  • Si no hay una carpeta no oculta allí, */se expandirá a sí misma, por lo que recibirá un mensaje de error al mvdecir que no puede encontrar un archivo llamado */data/*. Del mismo modo, si no hay un archivo no oculto en ninguna de las carpetas, recibirá un mensaje de error que that-folder/data/*no existe.
Stéphane Chazelas
fuente