Bash: combiens de champs dans une chaîne de caractères?

Bonjour,
La commande cut découpe une chaine en champs séparés par un caractère.
Un nom de chemin sépare chaque niveau par un « / »

Comment trouver le nombre de champs? (le niveau de profondeur du répertoire courant PWD)

Je cherche à lister chaque champs dans une boucle de tests, pour trouver le niveau du dépot .git/ utilisé (le répertoire courant, sinon son parent le plus proche)

Comment programmer cette boucle?
soit en connaissant le nombre de champs (for champs in {0…$nombreDeChamps}; do …),
soit autrement (si vous avez une idée…).

Le test principal est le suivant (trouver un dépot .git dans le répertoire):
ls -1A | egrep '\.git$' && echo 'OK'

Bonjour

En bash :

michel@ubuT450:~/Téléchargements/ISOsInstall$ myPWD=$PWD; compt=0
michel@ubuT450:~/Téléchargements/ISOsInstall$ until test -z "$myPWD"; do echo "niveau $((compt++)) -> $myPWD"; myPWD=${myPWD%/*}; done
niveau 0 -> /home/michel/Téléchargements/ISOsInstall
niveau 1 -> /home/michel/Téléchargements
niveau 2 -> /home/michel
niveau 3 -> /home
michel@ubuT450:~/Téléchargements/ISOsInstall$ 

Je n’utilise pas git
alors je n’ai sans doute pas pu bien comprendre quelle était la demande.

1 J'aime

Merci, c’est exactement la réponse espérée.
Un dépot git, c’est une arborescence qui commence par ./git/ dans un répertoire, et qui gère des fichiers avec des commandes « git » dans cette arborescence ( à base de diff/patch, d’index et de liens, si j’ai bien compris).

Les commandes git sont prises en compte dans le répertoire qui contient ce « dépôt » git (= cette arborescence cachée), mais aussi dans tous ses sous-répertoires, récursivement.

Donc, si un nouveau dépôt git est créé dans un sous-répertoire, ce sera alors ce dépôt git qui sera utilisé à partir de ce sous-répertoire et de sa descendance.

Je ne crée un dépôt git que quand je me rend compte que je vais en avoir besoin. Donc, avant de lancer une commande «git », je voudrais savoir à quel niveau ma commande sera traitée.

Par exemple, si j’ai créée une nouvelle arborescence à partir de la racine et que je lance une commande git, elle sera traitée par le dépôt existant dans la racine, en général déjâ bien encombrée. Je crée donc un autre dépôt spécifique dans un sous-répertoire.
Au bout d’un certain temps, je ne sais plus très bien à quel niveau la commande souhaitée sera traitée.

Ce script devra me donner la liste et l’emplacement des dépôts git concernés, c’est à dire la liste des répertoires « .git/ » du répertoire courant et de tous ses ancêtres

Votre réponse est-donc ce que je cherchais
encore merci

Une alternative utilisant grep et wc pour compter le nombre de slashs dans un chemin :

CHEMIN='play.it/repositories/scripts.git/.git'
echo "$CHEMIN" | grep --fixed-strings --only-matching --regexp='/' | wc --lines

Et sa version courte :

CHEMIN='play.it/repositories/scripts.git/.git'
echo "$CHEMIN" | grep -Fo '/' | wc -l

En reprenant la même méthode que j’avais utilisé,
mais en la basant sur les 4 dernières lettres du nom du répertoire ".git"

myPWD="$PWD"; compt=0
until test "${myPWD:(-4)}" = ".git"; do myPWD="${myPWD%/*}"; compt=$((compt+1)); done
echo -e "Le répertoire courant\t: $PWD\nest au niveau $compt de\t: ${myPWD##*/} -> $myPWD"

ce qui donne :

Le répertoire courant	: /home/michel/monProjet.git/rep1/rep2/rep3
est au niveau 3 de		: monProjet.git -> /home/michel/monProjet.git

Il y a aussi awk qui fait le travail de grep et wc

CHEMIN='play.it/repositories/scripts.git/.git'
awk -F/ '{print NF-1}' <<< $CHEMIN

Un basename en pur bash !

Voici le cœur de mon script « QuelGit.sh ».
Il ne renvoie rien si un dépôt existe dans ce répertoire, sinon il affiche le chemin qui sera affecté par les commandes git.

#!/bin/bash --
# Quel est le dépot /.git/ utilisé dans ce répertoire?
# 1 Existe-t-il dans ce répertoire?
ls -A | egrep -q '\.git$' &&  exit 0
# 2 sinon dans l'arbre parent:
myPWD="$PWD"
until [[ -z "$myPWD" ]]  ; do 
    ls -1A "$myPWD" | grep -Eq '\.git$' #&& ls -Ad "${myPWD}/.git" ;
    Retour="$?"
    # Trouvé, alors stop:
    if [[ "$Retour" == 0 ]]  ; then 
        ls -Ad "${myPWD}/.git"
        break 
    fi
    # Sinon suivant:
    myPWD=${myPWD%/*}; 
done

Dans mon script, j’ai ajouté une option «débogage» et une option «liste complète».
La liste complète peut — rarement — être utile lorsque j’ai créé un nouveau dépôt, mais que ce sous-répertoire a déjà utilisé git sur un dépôt ancêtre, pour le cas où je devrais remonter dans ces temps plus anciens.

Je n’ai peut être pas bien compris l’arborescence de ton .git
j’ai cru comprendre que tu voulais voir s’afficher
le premier répertoire parent dont le nom est .git

#!/bin/bash

[[ "$PWD" =~ "/.git" ]] || exit 1          # si pas de répertoire .git, alors quitter de suite avec code d'erreur à 1
myPWD="$PWD"
until test "${myPWD:(-5)}" = "/.git"; do   # Jusqu'à ce que les 5 derniers caractères du chemin courant soient : "/.git"
    myPWD="${myPWD%/*}"                    #   passer au répertoire parent
done
echo "$myPWD"                              # Afficher le chemin trouvé.

1 Le sous-répertoire .git/ est dans le répertoire courant: dans ce cas mon script reste silencieux.
2 Dans le cas contraire, il affiche effectivement le répertoire parent le plus proche qui contient .git/.

Ici j’ai réduit mon script pour ne pas l’encombrer avec la gestion des options. J’avoue ne pas l’avoir testé. Effectivement il ne fonctionne pas.
Je vous joins le script fonctionnel (sous réserve des bugs, comme il se doit!)→ QuelGit.txt (1,5 Ko)

(Les commandes TITRE et DEBUG sont des bibliothèques personnelles, et peuvent être remplacées par «echo» ou «echo -e»)
Ma bibliothèque est publiée ici (une vieille version…).