Wie ersetzt man einen Ordner, dessen Name ein Datum ist, dh YYYYMMDD, durch die Ordnerhierarchie von Jahr, Monat, Datum?

Ich habe eine Liste von Ordnern, die Datumsangaben für Namen haben. Die Datumsangaben haben das Format JJJJMMTT (z. B. 20150129). In diesen Ordnern befinden sich Textdokumente, die sich auf dieses bestimmte Datum beziehen.

Ich möchte sie in einer Ordnerhierarchie von Jahr zu Monat bis Datum neu strukturieren und die Textdokumente in den entsprechenden Ordner "Datum" weiter unten in der Hierarchie verschieben.

Mit anderen Worten, ich möchte, dass der Stammordner nach dem Jahr wie 2015 benannt wird, und dann Unterordner mit Namen wie 01 erstellt und dann weitere Unterordner mit Datumsangaben wie 29 erstellt, die die entsprechenden Textdokumente enthalten .

Der Pfad würde also wie folgt aussehen 2015/01/29/file.txtoder 2015>01>29>file.txt.

Ich habe mir Automator angesehen und es scheint, dass so etwas nicht möglich ist, obwohl ich mich irren könnte, also würde ich gerne wissen ...

  1. Gibt es eine einfache Lösung für dieses Problem, die jeder Laie verstehen kann, beispielsweise einen Automator-Workflow, oder erfordert dies ein gewisses Verständnis von Terminalbefehlen und regulären Ausdrücken?

  2. Wie würde man dieses Problem lösen, sofern es tatsächlich eine Lösung gibt?

Wer auch immer dafür gestimmt hat, diese Frage als "zu weit gefasst" zu schließen, warum? Ich frage mich, was an dieser Frage "zu breit" ist?
Befinden sich diese YYYYMMDD-Ordner alle direkt in einem Hauptordner oder sind sie über eine breitere Hierarchie verteilt?
@patrix In meinem Fall befinden sie sich alle im selben Verzeichnis oder Hauptordner

Antworten (2)

Angenommen, alle diese YYYYMMDD-Ordner sind Teil desselben übergeordneten Verzeichnisses, das Sie ausführen könnten

cd PARENT_DIRECTORY
for d in */; do
    [[ $d =~ [0-9]{8}/ ]] || continue
    mkdir -p -- "${d:0:4}/${d:4:2}"
    mv -- "$d" "${d:0:4}/${d:4:2}/${d:6:2}"
done
  • Die for d in */; doSchleife liest alle Verzeichniseinträge, das Trailing /stellt sicher, dass nur Verzeichnisnamen tatsächlich übereinstimmen
  • [[ $d =~ [0-9]{8}/ ]]testet, ob die aktuelle Eingabe aus 8 Ziffern besteht, und fährt mit der nächsten Eingabe fort, wenn nicht
  • ${d:0:4}/${d:4:2}/${d:6:2}verwendet die Parametererweiterung innerhalb bash, um eine Zeichenfolge zu erstellen, die den neuen Pfad enthält
  • Das --in beiden verhindert Probleme mkdir, mvfalls der Verzeichnis- oder Dateiname mit einem -. Dies kann hier nicht passieren, aber es ist wahrscheinlich trotzdem eine gute Praxis.

Danke an @terdon und @user3439894 für Ideen zur Verbesserung des ursprünglichen Skripts.

Danke für die Antwort, das funktioniert einwandfrei! Ich halte diese Lösung für besser als die von @grgarside, da sie viel schneller ist, insbesondere wenn es sich um einen riesigen Korpus mit Tausenden von Textdokumenten handelt.

Sie können Folgendes im Terminal verwenden. cdin den enthaltenden Ordner, und führen Sie dann Folgendes aus:

find . -type f -exec bash -c \
  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})#\1/\2/\3#" <<< $1);\
  mkdir -p -- $(dirname "$F");\
  mv -- "$1" "$F"' - {} \;

find . -type ferhält jede Datei im aktuellen Verzeichnis rekursiv.
-exec bash -cöffnet eine Shell, um die folgenden Befehle auszuführen.
F=$(…)öffnet eine Subshell und verwendet sed für den Dateipfad, um den Pfad in die Ordner zu manipulieren.
^\./([0-9]{4})([0-9]{2})([0-9]{2})ist eine Regex mit drei Erfassungsgruppen, wie folgt: ist Ersatz, wobei jede Erfassungsgruppe ( , usw.) durch getrennt ist . erstellt die Verzeichnisse, in die die Dateien verschoben werden. verschiebt jede Datei in den entsprechenden Ordner.
\1/\2/\3\1/
mkdir -p -- $(dirname "$F")
mv -- "$1" "$F"

Dies nimmt die Hierarchie auf der linken Seite und konvertiert sie in die Hierarchie auf der rechten Seite:

├── 20170201               └── 2017
│   └── abcdefghij             ├── 02
└── 20170302                   │   └── 01
    └── abcdefghij 2           │       └── abcdefghij
                               └── 03
                                   └── 02
                                       └── abcdefghij 2

Wenn sich im enthaltenden Ordner andere Dateien mit einem Datum als Namen befinden, werden sie verschoben, als wären sie ein Ordner. Um dies zu verhindern, ersetzen Sie die zweite Zeile durch:

  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})(?:/.+)#\1/\2/\3#" <<< $1);\

Das (?:/.+)stellt sicher, dass der Pfad eine nachfolgende Komponente hat, und ignoriert daher alles ohne untergeordnete Elemente im übergeordneten Verzeichnis, bei denen es sich um Dateien handelt.

@ klanomathregex101.com
@grgarside Danke