Créez un dossier «Photo» dans tous les répertoires de manière récursive

9

J'ai un tas de dossiers et je veux parcourir tous ces dossiers et dans chaque dossier créer un autre dossier nommé "Photo"

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

Je veux avoir:

F1
--Photo
--F11
----Photo
----F111
------Photo
----F112
------Photo
--F12
----Photo
OOzy Pal
la source

Réponses:

8

À partir du répertoire juste au-dessus de F1, exécutez ce script:

Le but du script est d'éviter la création de répertoires de photos redondants sous les répertoires de photos.

En outre, il est conçu pour éviter de l'exécuter accidentellement à partir d'un mauvais emplacement tel que le répertoire racine de l'utilisateur, alors qu'il ne verrait pas le F1répertoire et ne créerait pas par erreur des centaines de répertoires de photos dans les mauvais palais.

De plus, j'avais l'intention de créer un script facile à suivre afin que l'utilisateur puisse le personnaliser.

#!/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)

Script mis à jour:

  • Changé les minuscules pen photomajuscules.
  • Ajout de la prise en charge des noms de fichiers non autonomes (avec des suggestions de Terdon).
LD James
la source
1
J'éviterais certainement d' analyser ls , cela peut échouer de manière inhabituelle. Je pense que les réponses qui évitent cela sont probablement plus sûres.
Arronical
3
@Arronical lsn'est pas analysé. C'est juste une rétroaction à l'utilisateur ... montrant ce qui se passe. Tout comme les mots "Ceci est un répertoire de photos". C'est faire savoir à l'utilisateur pourquoi il n'y crée pas de répertoire.
LD James
1
J'avais pensé que cela pourrait être le cas, car je ne voyais rien en faire. Dans ce cas, je retire mon commentaire et je
descends
find -type d F1, peut être?
Olivier Grégoire
Notez que cela échouera s'il y a un fichier (et non un répertoire) appelé $i/Photo, mais l'OP n'a pas spécifié ce qui doit être fait dans un tel cas. Il échouera également dans le cas, certes peu probable, où l'un des $is contient une nouvelle ligne.
terdon
24

Vous pouvez y parvenir en utilisant un seul findappel.

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

La partie -name 'Photo' -prune -oindique de ne pas récuser dans les Photorépertoires existants (et nouvellement créés) : Si le fichier (ou répertoire) trouvé a le nom Photo, arrêtez de le traiter ( -prune). Dans l'autre cas ( -o), continuez avec directory ( -type d) et exécutez ( -exec) la commande.

Melebius
la source
ah bien, je l'ai essayé de cette façon et je vois dans votre réponse où je me trompais :)
Zanna
@Zanna -prune? :) Oui, c'est assez contre-intuitif mais ça vaut le coup d'être appris.
Melebius
Arrêtera-t-il de créer un dossier 'Photo' si un fichier nommé 'Photo' existe?
Anwar
3
@Anwar La version actuelle le sera. Il y a une zone grise dans les exigences. :) Vous pouvez changer cela en spécifiant -type davec -name 'Photo'avant -prune.
Melebius
2
@Anwar Au deuxième coup d'œil, cela n'a aucun sens. Vous ne pouvez pas créer un dossier portant le même nom qu'un fichier normal dans le même dossier. Et findcontinuera avec d'autres dossiers (y compris les sous-dossiers de ce dossier, si vous le demandez).
Melebius
9

Vous pouvez passer les findrésultats à la whileplace de forcar de cette façon, il ne se cassera pas si les noms de fichiers ont des espaces

Cd dans le répertoire F1, puis faites:

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

Si le répertoire existe, mkdirrefusera simplement de le créer, donc pas de problème là-bas ...

Si les noms de vos répertoires peuvent contenir des sauts de ligne ou d'autres étrangetés exotiques, utilisez ceci qui peut traiter des noms arbitraires:

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

Merci à @terdon pour son aide :)

Zanna
la source
Si le F1répertoire de l'op est ~user/Pictures, le déplacement vers le répertoire parent et l'exécution de la ligne mettront un Photorépertoire dans chaque répertoire de son espace, qui pourrait être des milliers. Pensez à ajouter le F1dans le cadre de la ligne de communication pour éviter une erreur facilement commise. De cette façon, s'il est exécuté par inadvertance au mauvais endroit, il ne créera pas de répertoires.
LD James
ah ouais j'étais en fait pas sûr de leur structure de répertoires. Je suggère de le faire à la F1place, édité @LDJames
Zanna
5

Python avec os.walkpeut le faire assez facilement et en seulement quelques lignes de code

$ 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

Explication

Nous avons affaire à cette commande: python -c 'import os; [os.mkdir (r + "/ Pictures") pour r, d, f dans os.walk (".")]'

Ici, nous appelons simplement l'interpréteur python avec -cflag pour spécifier la commande que nous donnons entre guillemets simples. os.walk()La fonction nous permet de parcourir récursivement tous les sous-répertoires et pour chaque sous-répertoire (représenté par r), nous créons un dossier Images via la os.mkdir()fonction. r+"/Pictures"est juste une simple manipulation de chaîne pour joindre la chaîne de sous-répertoire et la chaîne "/ Pictures" pour former un seul chemin

Remplacez "/ Pictures" par "/ Photo" pour répondre à vos besoins

Sergiy Kolodyazhnyy
la source
4

Si vous utilisez bash, vous pouvez simplement exécuter:

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

L' globstaroption fait **correspondre "tous les fichiers et 0 ou plusieurs répertoires et sous-répertoires". En d'autres termes, il correspond à tout de manière récursive. En raison de la /fin, **/correspondra à tous les répertoires et sous-répertoires (pas de fichiers). Par conséquent, le $ditérera sur tous les répertoires du répertoire actuel et leurs sous-répertoires et le Photosrépertoire sera créé dans chacun d'eux.

Le -pdrapeau des mkdirmoyens:

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

Ici, je l'utilise simplement pour supprimer les messages d'erreur si le répertoire cible existe déjà. Supprimez-le si vous souhaitez voir les erreurs.

Notez que cela ne permettra pas de créer un Photosous - répertoire dans un répertoire cible qui contient un fichier nommé Photo. Cependant, vous n'avez pas spécifié ce qui devrait être fait dans ces cas et toutes les autres réponses publiées jusqu'à présent ont également cette limitation.

terdon
la source