Ich habe folgende Dateistruktur:
- /home/daten/C01/dir_wwe_346/datei1.txt Bild.jpg zufällig.sh
- /home/daten/C02/dir_wwe_644/datei1.txt Bild.jpg zufällig.sh
- /home/daten/C03/dir_wwe_324/datei1.txt Bild.jpg zufällig.sh
Ich möchte, dass sie so sind:
- home/data/C01/file1.txt Bild.jpg random.sh
- home/data/C02/file1.txt Bild.jpg random.sh
- home/data/C03/file1.txt Bild.jpg random.sh
Dabei werden im Grunde mehrere Dateien ein Verzeichnis nach oben verschoben. Ich habe dieses Skript erfolglos ausprobiert:
#!/bin/bash for i in */ do cd i/*/ mv * ../ done
Nachdem ich dies gepostet hatte (aber bevor ich die Grawity-Antwort unten gelesen hatte), wurde mir klar, dass ich nicht die richtige Variablenerweiterung verwendet hatte, und führte Folgendes aus:
#!/bin/bash for i in */ do cd ${i}*wwe* mv * ../ done
Das Skript verschiebt alle Unterverzeichnisse in den Datenordner, sodass ich am Ende Folgendes erhalte:
- /heim/C01/dir_wwe_346/datei1.txt Bild.jpg zufällig.sh
- /heim/C02/dir_wwe_644/datei1.txt Bild.jpg zufällig.sh
/heim/C03/dir_wwe_324/datei1.txt Bild.jpg zufällig.sh
Was mache ich falsch?
PS. Ich habe den Beitrag so bearbeitet, dass er den Prozess zeigt, den ich durchlaufen habe, und damit die Antworten für Neulinge, die von diesen Antworten profitieren könnten, mehr Sinn ergeben. Danke Grawity, ich habe etwas Neues gelernt. Ich habe erst vor einer Woche angefangen, Bash zu lernen, und ich habe das Gefühl, dass ich Fortschritte mache.
Antwort1
Variablen werden nur mit dem
$
Präfix erkannt und erweitert. Wenn die Schleife eine Variable 'i' definiert, müssen Sie verwenden$i
wann immer Sie den Wert benötigen:for i in */; do cd $i/*/
Das „aktuelle Verzeichnis“ ist prozessweit gültig und wird nicht bei jedem Schleifendurchlauf automatisch zurückgesetzt. Sie müssen anschließend entweder manuell in das übergeordnete Verzeichnis zurückkehren:
cd $i/*/; mv * ../; cd ../../
oder verwenden Sie eine „Subshell“, um den Verzeichniswechsel einzuschränken:
(cd $i/*/; mv * ../)
Sie führen keine Fehlerprüfung durch. Wenn das
cd
jemals fehlschlägt,mv
kann das Nachfolgende unangenehme Dinge tun. Verbinden Sie Befehle entweder mit&&
oder führen Sie die entgegengesetzte Prüfung durch und verwenden Sie|| exit
(oder|| break
), je nachdem, was am besten aussieht:for i in */; do cd $i/*/ && { mv * ../; cd ../../ } done for i in */; do cd $i/*/ || exit mv * ../ cd ../../ done for i in */; do (cd $i/*/ && mv * ../) done
Verbesserung: Sie können den Unterverzeichnis-Platzhalter nach verschieben
mv
, sodass es auch funktioniert, wenn mehrere Unterverzeichnisse vorhanden sind:cd $i/ || exit mv */* . cd ../
Verbesserung: Sie können dies tun, ohne Folgendes
cd
überhaupt zu benötigen:mv $i/*/* $i/