2

I got a project with multiple submodules, I want to list for each submodule it depth relatively The project:

main_project
    submodule1
    submodule1\submodule1_1
    submodule1\submodule2_1\submodule2_1_1
    submodule2\submodule2_1\submodule2_1_1\submodule2_1_1_1\
    submodule3

The output I want to get:

submodule1 - level 0
submodule1\submodule1_1 - level 1
submodule1\submodule2_1\submodule2_1_1 - level 2
submodule2\submodule2_1\submodule2_1_1\submodule2_1_1_1\ - level 3
submodule3 - level 0
Ziv M
  • 409
  • 6
  • 18
  • tried to count "/" as relative position to the main project git submodule foreach --recursive "pwd | wc -c'/'" But it doesn't work.... – Ziv M Dec 16 '20 at 14:25
  • Are you looking for : [Count occurrences of a char in a string using Bash](https://stackoverflow.com/questions/16679369/count-occurrences-of-a-char-in-a-string-using-bash) ? – LeGEC Dec 16 '20 at 14:51
  • @LeGEC tried it as an option git submodule foreach --recursive "awk -F"${char}" '{print NF}' <<< pwd" But seems something went wrong – Ziv M Dec 16 '20 at 14:58
  • that's a one liner. Have you tried writing it in two lines ? :) – LeGEC Dec 16 '20 at 15:47
  • You are having issues with escaping the script you are passing inside the `"..."` argument to `git submodule foreach ...`. You can solve the escaping problems by writing your command in a file (e.g `/tmp/count.sh`) and call `git submodule ... /tmp/count.sh`. – LeGEC Dec 16 '20 at 15:49
  • an answer like @phd's looks more robust, though – LeGEC Dec 16 '20 at 15:51

1 Answers1

2
git submodule foreach -q --recursive git rev-parse --git-dir |
    awk '{split($0, a, "/modules/", s); print $0, "- Level", length(s)-1}'

Explanation:

git submodule foreach -q --recursive

Run a command on all submodules recursive.

git rev-parse --git-dir

Run this command for every submodule — show the path to its .git/modules directory. Example:

$ git submodule foreach -q --recursive git rev-parse --git-dir

$root/.git/modules/mod1
$root/.git/modules/mod2
$root/.git/modules/mod3
$root/.git/modules/mod3/modules/subdir/submodule

All modules in the example are level 0 modules, the last one is level 1. Counting slashes wouldn't help as there are subdirectories (a subsubmodule buried deeper than the root of a submodule). Let's count /modules/ with awk:

awk '{split($0, a, "/modules/", s); print $0, "- Level", length(s)-1}'

Every input line is split by /modules/ and the list of separators is put into the array s. Then we just count the number of /modules/ and nicely print the result:

git submodule foreach -q --recursive git rev-parse --git-dir |
    awk '{split($0, a, "/modules/", s); print $0, "- Level", length(s)-1}'

$root/.git/modules/mod1 - Level 0
$root/.git/modules/mod2 - Level 0
$root/.git/modules/mod3 - Level 0
$root/.git/modules/mod3/modules/subdir/submodule - Level 1

Print submodules workdirs:

$ git submodule foreach -q --recursive 'pwd; git rev-parse --git-dir' |
    awk 'NR%2==1 {submodule=$0} NR%2==0 {split($0, a, "/modules/", s); print submodule, "- Level", length(s)-1}':

$root/mod1 - Level 0
$root/third-party/mod2 - Level 0
$root/third-party/mod3 - Level 0
$root/third-party/mod3/subdir/submodule - Level 1
phd
  • 82,685
  • 13
  • 120
  • 165