
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, -depth
sollte 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
, /A
die B
Unterverzeichnisse 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