Disons que j'ai les éléments suivants:
./
Dir1/
Sub1/
Sub1.jpg
Sub2/
Sub2.jpg
Sub2.png
Sub2.txt
Dir2/
Sub1/
Sub1.doc
Sub1.txt
Sub2/
Sub2.jpg
Sub2.png
SomeTxt.txt
Dir3/
Dir3.txt
Dir4/
Sub1/
Dir4.txt
Some.txt
En utilisant bash (bashrc dans mon cas), comment puis-je obtenir une variable contenant tous les répertoires contenant un fichier texte (.txt) portant le même nom que le répertoire contenant? Donc, à partir de l'exemple ci-dessus, j'aimerais avoir une variable contenant ce qui suit:
./Dir1/Sub2/
./Dir1/Sub1/
./Dir3/
Il ne devrait pas retourner ./Dir1/Sub1/
car il ne possède pas de fichier Sub1.txt
.
Il ne devrait pas renvoyer ./Dir2/Sub2/
car le fichier txt qu'il contient n'est pas Sub2.txt
.
Il ne devrait pas retourner ./Dir4/
ou ./Dir4/Sub1/
parce que Dir4.txt
n'est pas directement dans ./Dir4/
.
NOTE:
Les noms des répertoires ne doivent pas être ces noms en particulier. Ce qui est important, c'est que le nom du fichier txt corresponde au nom du répertoire contenant.
De plus, je sais que d'autres langues sont peut-être plus faciles, mais j'en ai besoin à bash.
Donné
$ tree somepath/
somepath/
├── Dir1
│ ├── Sub1
│ │ └── Sub1.jpg
│ └── Sub2
│ ├── Sub2.jpg
│ ├── Sub2.png
│ └── Sub2.txt
├── Dir2
│ ├── Sub1
│ │ ├── Sub1.doc
│ │ └── Sub1.txt
│ └── Sub2
│ ├── SomeTxt.txt
│ ├── Sub2.jpg
│ └── Sub2.png
├── Dir3
│ └── Dir3.txt
└── Dir4
├── Some.txt
└── Sub1
└── Dir4.txt
9 directories, 12 files
puis, avec l'option globstar du shell activée (shopt -s globstar
)
for d in somepath/**/; do
d="${d%/}"
[[ -f "${d}/${d##*/}.txt" ]] && printf "%s\n" "$d"
done
somepath/Dir1/Sub2
somepath/Dir2/Sub1
somepath/Dir3
Si vous souhaitez stocker les résultats dans un tableau pour un traitement ultérieur, vous pouvez le faire en utilisant le mapfile
intégré au shell (ou son synonyme readarray
), par exemple.
mapfile -t TXT_DIRS < <(
for d in somepath/**/; do
d="${d%/}"
[[ -f "${d}/${d##*/}.txt" ]] && printf "%s\n" "$d"
done
)
REMARQUE: , il serait préférable de mettre la liste en terminaison nulle en utilisant l'une des méthodes décrites dans . bash: utilisation procédurale de find dans select dans les espaces libres
Vous pouvez ensuite parcourir le tableau comme si
for d in "${TXT_DIRS[@]}"; do
echo "$d"
done
somepath/Dir1/Sub2
somepath/Dir2/Sub1
somepath/Dir3
Alternativement, vous pouvez éviter de stocker les résultats et simplement traiter chaque répertoire au fur et à mesure que vous le trouvez, c'est-à-dire.
for d in somepath/**/; do
d="${d%/}"
[[ -f "${d}/${d##*/}.txt" ]] && echo "Doing something with $d"
done
Doing something with somepath/Dir1/Sub2
Doing something with somepath/Dir2/Sub1
Doing something with somepath/Dir3
C'est pratiquement la même chose que la réponse de steeldriver, mais elle passe en boucle sur chaque fichier txt au lieu de chaque répertoire. J'espère que c'est aussi plus facile à comprendre.
Comme vous avez mentionné dans un commentaire que vous n’avez pas réellement besoin d’un tableau, j’ai omis cette étape.
shopt -s globstar
for f in ./**/*.txt; do
d="$(dirname "$f")"
if [[ $(basename "$f") == $(basename "$d").txt ]]; then
printf '%s\n' "$d"
fi
done
Sortie:
./Dir1/Sub2
./Dir2/Sub1
./Dir3