Erstellen Sie rekursiv einen Ordner "Foto" in allen Verzeichnissen


9

Ich habe eine Reihe von Ordnern und möchte alle diese Ordner durchlaufen und in jedem Ordner einen anderen Ordner mit dem Namen "Foto" erstellen.

F1
--F11
----F111
----F112
--F12

Ich möchte haben:

F1
--Photo
--F11
----Photo
----F111
------Photo
----F112
------Photo
--F12
----Photo

Antworten:


8

Führen Sie aus dem Verzeichnis direkt über F1 dieses Skript aus:

Mit dem Skript soll vermieden werden, dass redundante Fotoverzeichnisse unter Fotoverzeichnissen erstellt werden.

Außerdem soll verhindert werden, dass es versehentlich von einem falschen Speicherort wie dem Stammverzeichnis des Benutzers ausgeführt wird, während das F1Verzeichnis nicht angezeigt wird und versehentlich Hunderte von Fotoverzeichnissen in den falschen Palästen erstellt werden.

Außerdem war es meine Absicht, ein einfach zu befolgendes Skript zu erstellen, damit der Benutzer es anpassen kann.

#!/bin/bash

while IFS= read -r -d '' i;
do
    if [[ ! -d $i/Photo ]]; then
        # Filter to skip folders named Photo
        thisfolder="$(echo $i | sed "s/.*\///")"
        if [[ ! $thisfolder == "Photo" ]]; then
            mkdir "$i/Photo"
        fi
    fi
done < <(find F1 -type d -print0)

Skript aktualisiert:

  • Kleinbuchstaben pin photoGroßbuchstaben geändert .
  • Unterstützung für nicht stander Dateinamen hinzugefügt (mit Vorschlägen von Terdon).

1
Ich würde es definitiv vermeiden, ls zu analysieren , es kann auf ungewöhnliche Weise fehlschlagen. Ich denke, die Antworten, die dies vermeiden, sind wahrscheinlich sicherer.
Arronical

3
@Arronical lswird nicht analysiert. Es ist nur ein Feedback an den Benutzer ... das zeigt, was passiert. Genau wie die Worte "Dies ist ein Fotoverzeichnis". Der Benutzer wird darüber informiert, warum dort kein Verzeichnis erstellt wird.
LD James

1
Ich hatte gedacht, dass dies der Fall sein könnte, da ich nicht sehen konnte, dass etwas damit gemacht wurde. In diesem Fall
ziehe

find -type d F1, vielleicht?
Olivier Grégoire

Beachten Sie, dass dies fehlschlägt, wenn eine Datei (und kein Verzeichnis) aufgerufen $i/Photowird, das OP jedoch nicht angegeben hat, was in einem solchen Fall zu tun ist. $iDies wird auch in dem zugegebenermaßen unwahrscheinlichen Fall fehlschlagen, in dem eines der s eine neue Zeile enthält.
Terdon

24

Sie können dies mit einem einzigen findAnruf erreichen.

find . -name 'Photo' -prune -o -type d -exec mkdir {}/Photo \;

Der Teil -name 'Photo' -prune -oweist darauf hin, dass nicht auf vorhandene (und neu erstellte) PhotoVerzeichnisse zurückgegriffen werden soll: Wenn die gefundene Datei (oder das gefundene Verzeichnis) den Namen hat Photo, beenden Sie die Verarbeitung ( -prune). Im anderen Fall ( -o) fahren Sie mit Verzeichnissen ( -type d) fort und führen Sie -execden Befehl ( ) aus.


ah schön, ich habe es so versucht und ich sehe aus deiner Antwort, wo ich falsch gelaufen bin :)
Zanna

@ Zanna -prune? :) Ja, es ist ziemlich kontraintuitiv, aber es lohnt sich zu lernen.
Melebius

Wird die Erstellung eines Ordners "Foto" beendet, wenn eine Datei mit dem Namen "Foto" vorhanden ist?
Anwar

3
@Anwar Die aktuelle Version wird. Die Anforderungen enthalten eine Grauzone. :) Sie können dies ändern, indem Sie -type dzusammen mit -name 'Photo'vorher angeben -prune.
Melebius

2
@Anwar Auf den zweiten Blick macht es keinen Sinn. Sie können keinen Ordner mit demselben Namen wie eine reguläre Datei innerhalb desselben Ordners erstellen. Und findwird mit anderen Ordnern fortfahren (einschließlich Unterordnern dieses Ordners, wenn Sie danach fragen).
Melebius

9

Sie können findErgebnisse an übergeben, whileanstatt, forda auf diese Weise die Dateinamen nicht unterbrochen werden

Zuerst CD in das Verzeichnis F1, dann:

find -type d | while read dir ; do mkdir "$dir"/Photo ; done

Wenn das Verzeichnis existiert, mkdirwird es einfach nicht erstellt, also kein Problem ...

Wenn Ihre Verzeichnisnamen Zeilenumbrüche oder andere exotische Fremdheiten enthalten könnten, verwenden Sie diese, die mit beliebigen Namen umgehen können:

find -type d -print0 | while IFS= read -r -d '' dir ; do mkdir "$dir"/Photo ; done

Vielen Dank an @terdon für die Hilfe dabei :)


Wenn sich das F1Verzeichnis des Ops befindet ~user/Pictures, wird beim Verschieben in das übergeordnete Verzeichnis und Ausführen der Zeile Photoin jedem Verzeichnis in seinem Bereich ein Verzeichnis abgelegt , das Tausende sein kann. F1Fügen Sie das als Teil der Kommanline hinzu, um einen leicht gemachten Fehler zu vermeiden. Auf diese Weise werden keine Verzeichnisse erstellt, wenn es versehentlich vom falschen Ort ausgeführt wird.
LD James

ah ja, ich war mir ihrer Verzeichnisstruktur nicht sicher. Ich schlage vor, es F1stattdessen zu tun , bearbeitet @LDJames
Zanna

5

Python mit os.walkkann es ziemlich einfach und in nur wenigen Codezeilen tun

$ mkdir dir_one dir_two
$ mkdir dir_two/dir_three
$ python -c 'import os;[os.mkdir(r + "/Pictures") for r,d,f in os.walk(".")]'                 
$ tree
.
├── dir_one
│   └── Pictures
├── dir_two
│   ├── dir_three
│   │   └── Pictures
│   └── Pictures
└── Pictures

Erläuterung

Wir haben es mit diesem Befehl zu tun: python -c 'import os; [os.mkdir (r + "/ Pictures") für r, d, f in os.walk (".")]'

Hier rufen wir einfach den Python-Interpreter mit -cFlag auf, um den Befehl in einfachen Anführungszeichen anzugeben. os.walk()Mit der Funktion können wir alle Unterverzeichnisse rekursiv durchlaufen. Für jedes Unterverzeichnis (dargestellt durch r) erstellen wir über die os.mkdir()Funktion den Ordner Bilder . r+"/Pictures"ist nur eine einfache Zeichenfolgenmanipulation, um die Unterverzeichniszeichenfolge und die Zeichenfolge "/ Pictures" zu einem Pfad zusammenzufügen

Ersetzen Sie "/ Pictures" durch "/ Photo", um Ihren Anforderungen zu entsprechen


4

Wenn Sie bash verwenden, können Sie einfach Folgendes ausführen:

shopt -s globstar
for d in **/; do mkdir -p "$d"/Photo; done

Mit dieser globstarOption werden **"alle Dateien und 0 oder mehr Verzeichnisse und Unterverzeichnisse" abgeglichen. Mit anderen Worten, es passt alles rekursiv an. Wegen der /am Ende **/werden alle Verzeichnisse und Unterverzeichnisse (keine Dateien) übereinstimmen. Daher $diteriert der über alle Verzeichnisse im aktuellen Verzeichnis und deren Unterverzeichnisse, und das PhotosVerzeichnis wird in jedem von ihnen erstellt.

Die -pFlagge der mkdirMittel:

  -p, --parents
          no error if existing, make parent directories as needed

Hier verwende ich es nur, um Fehlermeldungen zu unterdrücken, wenn das Zielverzeichnis bereits vorhanden ist. Entfernen Sie es, wenn Sie die Fehler sehen möchten.

Beachten Sie, dass dadurch kein PhotoUnterverzeichnis in einem Zielverzeichnis erstellt werden kann, das eine Datei mit dem Namen Photo enthält. Sie haben jedoch nicht angegeben, was in diesen Fällen zu tun ist, und alle anderen bisher veröffentlichten Antworten haben ebenfalls diese Einschränkung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.