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/
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.)
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:
data
.-i
option à mv
).*/
, 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.*/
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.