UNIX-Shell-Skripting: Wie verschiebe ich Dateien rekursiv ein Verzeichnis nach oben?

UNIX-Shell-Skripting: Wie verschiebe ich Dateien rekursiv ein Verzeichnis nach oben?

Ich habe eine große Anzahl kleiner Dateien, f, die in einer Verzeichnisstruktur wie folgt angeordnet sind:

/A/B/C/f

Auf der Ebene A gibt es 11 Verzeichnisse mit jeweils ca. 100 Verzeichnissen, auf der Ebene B wiederum ca. 30 Verzeichnisse mit jeweils einer Datei f.

Wie verschiebe ich alle Dateien eine Ebene nach oben? Beispiel: Bei diesem Satz von Dateien...

/A/B/C/f1
/A/B/C/f2
/A/B/C/f3
/A/B/C/f4

Ich möchte, dass das Verzeichnis /A/B/4 Dateien enthält, f1 bis f4. Das Entfernen des Verzeichnisses C ist nicht erforderlich.

Ich hoffe, dass dieses Problem gelöst werden kann und möglicherweise find, xargs, und betrifft whatnot. Irgendwelche Ideen?

Prost,

James

Antwort1

Mit GNU find (wie es unter Linux zu finden ist) oder jedem anderen Find, das Folgendes unterstützt, ist es ziemlich einfach -execdir:

find A -type f -execdir mv -i {} .. \;

Mit einem Standard find:

find A -type f -exec sh -c 'mv -i "$1" "${1%/*}/.."' sh {} \;

Mit zsh:

zmv -Q -o-i 'A/(**/)*/(*)(.)' 'A/$1$2'

Wenn die Verzeichnisstruktur immer die gleiche Verschachtelungsebene hat, ist keine rekursive Traversierung erforderlich (aber entfernen Sie zuerst leere Verzeichnisse):

for x in */*; do; echo mv -i "$x"/*/* "$x"/..; done

Antwort2

Für diesen Satz von Dateien würde das Folgende funktionieren:

$ cd /A/B/C/
$ mv ./* ../

Ich vermute aber, dass Ihr Problem etwas komplizierter ist. Ich kann darauf keine Antwort geben. Ich bin mir nicht ganz sicher, wie Ihre Verzeichnisstruktur ist. Könnten Sie das klarstellen?

Antwort3

Meine erste Vermutung ist

$ find A -type f -exec mv {} .. \;  

solange Sie nichts anderes angeben, -depthsollte es in Ordnung sein. Ich habe es NICHT ausprobiert, also testen Sie es zuerst, bevor Sie sich dazu verpflichten.

Antwort4

Wenn Sie nur Dateien verschieben möchten, die sich in Blattverzeichnissen befinden (d. h. Sie möchten sie nicht in Verzeichnisse verschieben /A/B/file, /Adie BUnterverzeichnisse enthalten), haben Sie hierfür mehrere Möglichkeiten:

Beide erfordern dies

leaf ()
{
    find $1 -depth -type d | sed 'h; :b; $b; N; /^\(.*\)\/.*\n\1$/ { g; bb }; $ {x; b}; P; D'
}
shopt -s nullglob

Das hier funktioniert:

leaf A | while read -r dir
do
    for file in "$dir"/*
    do
        parent=${dir%/*}
        if [[ -e "$parent/${file##*/}" ]]
        then
            echo "not moved: $file"
        else
            mv "$file" "$parent"
        fi
    done
done

Das geht zwar schneller, mag aber keine leeren Quellverzeichnisse:

leaf A | while read -r dir
do
    mv -n "${dir}"/* "${dir%/*}"
    remains=$(echo "$dir"/*)
    [[ -n "$remains" ]] && echo "not moved: $remains"
done

verwandte Informationen