Angenommen, ich habe eine Reihe von Dateien in einem Verzeichnis
filename-1.ext1
filename-1.ext2
filename-1.ext3
filename-2.ext1
filename-2.ext2
filename-2.ext3
filename-3.ext1
filename-3.ext2
filename-3.ext3
Ich möchte dann Unterverzeichnisse im selben Verzeichnis mit demselben Namen wie die Dateien erstellen (Dateiname, aber keine Erweiterung) und sie wie folgt verschieben
filename-1
├──filename-1.ext1
├──filename-1.ext2
└──filename-1.ext3
filename-2
├──filename-2.ext1
├──filename-2.ext2
└──filename-2.ext3
filename-3
├──filename-3.ext1
├──filename-3.ext2
└──filename-3.ext3
Was wäre der effizienteste Weg, dies zu erreichen?
Bearbeiten: ext1, ext2, ext3 dienen nur dazu, drei verschiedene Dateinamen anzuzeigen, wie .foo, .bar, .top, .coffee usw. Nicht, dass die Dateinamen ähnlich wären.
Antwort1
Da Sie verwenden zsh
, könnte dies folgendermaßen erfolgen:
for name (*.ext<->(.)) mkdir -p -- $name:r && mv -- $name $name:r
oder mit der bekannteren Langform der for
Schleife,
for name in *.ext<->(.); do
mkdir -p -- $name:r &&
mv -- $name $name:r
done
Dies durchläuft alle regulären Dateien, die dem Muster entsprechen, *.ext<->
wobei <->
eine beliebige Zahl übereinstimmen muss. Es ist der Glob-Qualifizierer (.)
, der die Übereinstimmung nur mit regulären Dateien erzwingt. Ändern Sie das gesamte Muster in , *.*(.)
wenn Sie den Dateinamen einer beliebigen regulären Datei abgleichen möchten, der einen Punkt enthält. Wir benötigen den Punkt, da Sie eine Dateinamenerweiterung später entfernen möchten. Um ein strengeres statt eines lockereren Musters zu verwenden, verwenden Sie etwas wie filename-<->.ext<->(.)
. Dieses Muster erfordert, dass Sie wissen, dass Sie Namen abgleichen möchten, die mit der Zeichenfolge beginnen filename-
.
Die $name:r
Erweiterung ergibt den gleichen Wert wie $name
, jedoch ohne die Erweiterung (d. h. nur die „Wurzel“ des Wertes).
Wir verwenden es, --
um beiden das Ende von Optionen zu signalisieren mkdir
und mv
um zu verhindern, dass Namen, die mit einem Bindestrich beginnen, mit Optionen verwechselt werden.
Antwort2
Mit zmv
:
autoload -Uz zmv # best in ~/.zshrc
mkmv() { mkdir -p -- $2:h && mv -- "$@"; }
zmv -P mkmv -n '(*).ext<->(#q.)' '$1/$f'
(entfernen -n
, wenn zufrieden).
Auf diese Weise profitieren Sie von zmv
den Plausibilitätsprüfungen von .
Antwort3
Verwenden Sie diese for
Schleife, die sowohl mit Bash- als auch mit Zsh-Shells kompatibel ist:
for file in *.*; do
[ -f "$file" ] &&
mkdir -p -- "${file%.*}" &&
mv -- "$file" "${file%.*}/"
done
-p
Optionmkdir
stellt sicher, dass die Datei vorhanden ist. Der Fehler wird nicht ausgelöst.%.*
entfernt die Erweiterung aus den Dateinamen.
Antwort4
Mit GNU Parallel (ein Tool, dessen Leistungsfähigkeit mir gerade erst bewusst wird):
ls | parallel 'mkdir -p {.}; mv -i {} {.}'
Da dies in keiner Weise an die CPU gebunden ist, wird es vermutlich parallel
keine Geschwindigkeitsvorteile bringen, ist aber immer noch kürzer als viele der anderen angebotenen Lösungen.
Und dies hängt nicht vom Muster der Dateinamen ab.