it-swarm.com.de

mv: kann nicht stat Keine solche Datei oder Verzeichnis im Shell-Skript

Ich habe ein Skript geschrieben, um einige Dateien von einem Ordner in einen anderen Ordner zu verschieben, aber ich habe den folgenden Fehler erhalten. Ich habe 2 Ordner überprüft und festgestellt, dass für 1 Ordner solche Dateien vorhanden sind und für einen anderen keine solchen Dateien vorhanden sind, aber warum alle "mv" anzeigen kann nicht stat Keine solche Dateien oder Verzeichnis "

    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
    [[email protected] tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/
    [[email protected] 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

das Skript lautet:

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

Ich habe es in /home/esolve/project/capture/tcp_50x50/

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

Die Anführungszeichen (') Dort verhindern, dass die Shell Globbing ausführt. Der Befehl * Wird buchstäblich an den Befehl mv übergeben. Dies schlägt fehl, da in den angegebenen Verzeichnissen keine Dateien mit dem Namen * Gefunden werden.

Ändern Sie dies in:

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

(Doppelte Anführungszeichen, um Probleme zu vermeiden, wenn Sie jemals einen Verzeichnisnamen mit Leerzeichen haben. * Außerhalb der Anführungszeichen.)

Sie erhalten jedoch weiterhin die Fehler für die leeren Verzeichnisse. (Gleicher Grund: Wenn die Datei keine Übereinstimmung mit dem Muster findet, übergibt sie das Muster selbst als Argument an den Befehl.)

26
Mat

Es gibt verschiedene Probleme mit Ihrem Code:

list=`ls dest_folder`

Sie speichern die Ausgabe von ls ohne die nachgestellten Zeilenumbrüche in $list. ls gibt die Liste der Dateinamen aus, die durch Zeilenumbrüche getrennt sind. newline ist ein ebenso gültiges Zeichen wie ein beliebiges in einem Dateinamen, sodass die Ausgabe nicht zuverlässig verwendet werden kann. Beispielsweise ist die Ausgabe von ls für ein Verzeichnis, das a und b enthält, dieselbe wie die für ein Verzeichnis, das eine Datei mit dem Namen a<newline>b Enthält.

 cd dest_folder

Sie prüfen nicht, ob dieser Befehl fehlgeschlagen ist. Im Allgemeinen sollten Sie den Exit-Status von Befehlen überprüfen. Dies gilt jedoch insbesondere für cd, da der Rest der Befehle davon ausgeht, dass Sie sich in diesem neuen Verzeichnis befinden. Dies kann dramatische Konsequenzen haben, wenn Sie dies nicht tun.

cwd=`pwd`

POSIX-Shells behalten bereits den (einen) Pfad zum aktuellen Verzeichnis in der Variablen $PWD Bei, sodass Sie hier nicht pwd </ Code> verwenden müssen (insbesondere im allgemeinen Fall seit dem Befehl) Durch Ersetzen werden nachgestellte Zeilenumbrüche aus dem Pfad entfernt. Außerdem akzeptiert mv relative Pfade, sodass Sie den absoluten Pfad nicht aufbauen müssen.

for folder in $list;do

Wenn Sie eine Variable nicht in Anführungszeichen setzen, wird der Operator split + glob in Shells verwendet. Das heißt, der Inhalt der Variablen wird aufgeteilt (auf den in $IFS Erwähnten Trennzeichen mit speziellen Regeln für die Leerzeichen), und jedes Element, das sich aus dieser Aufteilung ergibt, wird nach Platzhalterzeichen durchsucht, damit sie auf das erweitert werden können Liste der übereinstimmenden Dateien.

Hier möchten Sie die Aufteilung, jedoch nur für Zeilenumbruchzeichen, und Sie möchten das Globbing nicht, daher müssen Sie es deaktivieren:

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

Eine Variable ohne Anführungszeichen zu lassen, ist der Operator split + glob. Hier möchten Sie keine, also müssen Sie diese Variablen zitieren.

Wie bereits erwähnt, werden Platzhalter nur erweitert, wenn sie nicht in Anführungszeichen gesetzt sind. Sie müssen das * Aus den Anführungszeichen entfernen. Wenn Sie das Globbing früher mit set -f Deaktiviert haben, müssen Sie es mit set +f Wiederherstellen, bevor Sie diesen Befehl aufrufen.

Ein viel besserer Weg, es zu schreiben, wäre:

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

Ein paar Anmerkungen:

  • Dadurch werden versteckte Ordner ausgeschlossen und versteckte Dateien nicht aus den Ordnern data verschoben.
  • Wir prüfen dabei nicht, ob Dateien überschrieben werden (möglicherweise möchten Sie die Option -i Zu mv hinzufügen).
  • Wenn Sie */ Verwenden, durchlaufen wir nur Verzeichnisse, aber dies schließt auch symbolische Links zu Verzeichnissen ein. Wenn Sie dies nicht möchten, müssen Sie der Schleife ein [ -L "${folder%/}" ] && continue Hinzufügen.
  • Wenn sich dort kein nicht versteckter Ordner befindet, wird */ Zu sich selbst erweitert, sodass Sie eine Fehlermeldung von mv erhalten, die besagt, dass keine Datei mit dem Namen */data/* Gefunden werden kann. Wenn sich in keinem der Ordner eine nicht versteckte Datei befindet, wird die Fehlermeldung angezeigt, dass that-folder/data/* Nicht vorhanden ist.
8