web-dev-qa-db-fra.com

mv: Can't Stat Aucun fichier ou répertoire de ce type dans le script Shell

J'ai écrit un script pour déplacer certains fichiers d'un dossier vers un autre dossier mais j'ai eu l'erreur suivante, j'ai vérifié 2 dossiers et j'ai remarqué que pour 1 dossier il y avait de tels fichiers et un autre il n'y en avait pas, mais pourquoi tous montraient "mv ne peut pas stat Pas de tels fichiers ou répertoire "

    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

le script est:

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

Je l'ai couru dans /home/esolve/project/capture/tcp_50x50/

20
misteryes
mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

Les guillemets ('), cela empêche le Shell de faire un globbing. Le * est passé littéralement à la commande mv, qui échoue car il ne trouve pas les fichiers appelés * dans les répertoires indiqués.

Changez ceci en:

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

(Des guillemets doubles pour éviter les problèmes si vous avez un nom de répertoire contenant des espaces. * en dehors des guillemets.)

Vous obtiendrez toujours les erreurs pour les répertoires vides. (Même type de raison: si le fichier ne trouve pas de correspondance pour le modèle, il transmet le modèle lui-même comme argument à la commande.)

26
Mat

Il y a plusieurs problèmes avec votre code:

list=`ls dest_folder`

Vous stockez la sortie de ls sans les caractères de fin de ligne dans $list. ls affiche la liste des noms de fichiers séparés par des caractères de nouvelle ligne. newline est un caractère aussi valide que n'importe quel autre dans un nom de fichier, de sorte que la sortie ne peut pas être utilisée de manière fiable. Par exemple, la sortie ls d'un répertoire contenant a et b est la même que celle d'un répertoire contenant un fichier appelé a<newline>b.

 cd dest_folder

Vous ne vérifiez pas l'échec de cette commande. En général, vous devez vérifier l'état de sortie des commandes, mais c'est particulièrement vrai pour cd, car les autres commandes supposent que vous êtes dans ce nouveau répertoire, ce qui pourrait avoir des conséquences dramatiques lorsque vous ne l'êtes pas.

cwd=`pwd`

Les shells POSIX conservent déjà le (un) chemin vers le répertoire courant dans le $PWD variable, vous ne devriez donc pas avoir besoin d'utiliser pwd</code> ici (en particulier dans le cas général, car la substitution de commandes supprimerait les caractères de fin de ligne du chemin). De plus, mv accepte les chemins relatifs, vous n'avez donc pas besoin de construire le chemin absolu.

for folder in $list;do

Laisser une variable sans guillemets est l'opérateur split + glob dans les shells. Autrement dit, le contenu de la variable est divisé (sur les séparateurs mentionnés dans $IFS avec des règles spéciales pour les espaces blancs), et chaque élément résultant de cette division est recherché pour les caractères génériques afin qu'ils puissent être développés dans la liste des fichiers correspondants.

Ici, vous voulez le fractionnement, mais uniquement sur les caractères de nouvelle ligne, et vous ne voulez pas le globbing, vous devez donc le désactiver:

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

Encore une fois, laisser une variable sans guillemets est l'opérateur split + glob. Ici, vous ne voulez ni l'un ni l'autre, vous devez donc citer ces variables.

Comme déjà mentionné, les caractères génériques ne sont développés que lorsqu'ils ne sont pas cités, vous devez déplacer ce * hors des guillemets. Si vous avez désactivé la globalisation plus tôt avec set -f, vous devez le réactiver avec set +f avant d'appeler cette commande.

Une bien meilleure façon de l'écrire serait:

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

Quelques notes cependant:

  • Cela exclura les dossiers cachés et ne déplacera pas les fichiers cachés des dossiers data.
  • Nous ne vérifions pas que les fichiers sont remplacés dans le processus (vous souhaiterez peut-être ajouter le -i option à mv).
  • En utilisant */, nous bouclons sur répertoires uniquement, mais cela inclut également les liens symboliques vers les répertoires. Si vous préférez ne pas le faire, vous devez ajouter un [ -L "${folder%/}" ] && continue à l'intérieur de la boucle.
  • S'il n'y a pas de dossier non masqué là-dedans */ se développera sur lui-même, vous recevrez donc un message d'erreur de mv disant qu'il ne peut pas trouver un fichier appelé */data/*. De même, s'il n'y a aucun fichier non caché dans l'un des dossiers, vous obtiendrez un message d'erreur indiquant que that-folder/data/* n'existe pas.
8