Search code examples
linuxbashshellcommandsh

How can I use bash to show a hierarchy structure?


I have a csv file like below. The ID is the unique identifier of each employee, and the MANAGERID is the ID of his/her manager.

id,managerid,firstname,lastname,dob,address
1,0,John,A,1976-01-01,some where
108,12,Tom,B,1996-01-01,some where
85,12,Jerry,C,1975-01-01,some where
12,1,Winsor,D,1984-01-01,some where
16,85,Smith,H,1977-01-01,some where
100,0,Ray,G,1999-01-01,some where
22,100,Albert,B,1980-01-01,some where
17,22,Robert,J,1980-01-01,some where
21,22,Linda,K,1981-01-01,some where
35,17,Lily,J,1968-01-01,some where
101,0,Sam,A,1995-01-01,some where
105,101,Liz,Z,1988-08-08,earth

I want to use a bash command/script to print out the structure, like a tree. The top manager is the root, following by the department manager and the employees of the department. The ID & name of the top manager should also be listed aside the employees.

I dont have a clue how to do this yet.

The expected output should be like this.

1:John A(1:John A)
+12:Winsor D(1:John A)
+-85:Jerry C(1:John A)
+--16:Smith H(1:John A)
+-108:Tom B(1:John A)
100:Ray G(100:Ray G)
+22:Albert B(100:Ray G)
+-21:Linda K(100:Ray G)
+-17:Robert J(100:Ray G)
+--35:Lily J(100:Ray G)
101:Sam A(101:Sam A)
+105:Liz Z(101:Sam A)

Any help would be much appreciated!


Solution

  • If you have python installed, you can try this code. It works in python2 & python3.

    tree.py:

    import sys
    
    class Employee:
      def __init__(self, id, pid, name):
        self.id = id
        self.pid = pid
        self.name = name
        self.level = 0
        self.managerinfo = self.id+": "+self.name
    
    def printlist(rlist): 
      for e in rlist:
        print('+'.ljust(e.level+1,'-')+e.id+":"+e.name+"("+e.managerinfo+")")
    
    def insone(mylist, id, newe):
      idx=0
      for e in mylist:
        idx+=1
        if e.id == id:
          newe.level = e.level+1
          newe.managerinfo = e.managerinfo
          mylist.insert(idx,newe)
          #print('Insertint '+newe.id+':'+newe.name+' after '+e.id+':'+e.name)
          return True
      return False
    
    def sortlist(sorted,unsorted):
      #print("begin:"+str(len(unsorted)))
      if len(unsorted)<=0:
        return
      for u in unsorted:
        if u.pid == '0':
          sorted.append(u)
          unsorted.remove(u)
        else:
          if insone(sorted, u.pid, u):
            unsorted.remove(u)
      #print("end:"+str(len(unsorted)))
      sortlist(sorted,unsorted)
    
    if __name__ == "__main__":
    
      file1 = open(sys.argv[1], 'r')
      Lines = file1.readlines()
    
      rawlist=[]
      line=0
      for row in Lines:
        line+=1
        if line>1:
          a = row.strip().split(',')
          rawlist.append(Employee(a[0],a[1],a[2]+" "+a[3]))
    
      sortedlist = []
      sortlist(sortedlist,rawlist)
    
      printlist(sortedlist)
    

    Then run this,

    [ rquery]$ python tree.py samples/organization.csv
    +1:John A(1: John A)
    +-12:Winsor D(1: John A)
    +--85:Jerry C(1: John A)
    +---16:Smith H(1: John A)
    +--108:Tom B(1: John A)
    +100:Ray G(100: Ray G)
    +-22:Albert B(100: Ray G)
    +--17:Robert J(100: Ray G)
    +---35:Lily J(100: Ray G)
    +--21:Linda K(100: Ray G)
    +101:Sam A(101: Sam A)
    +-105:Liz Z(101: Sam A)
    

    Alternatively, if you can download rq, it can complete this task within one command line.

    [ rquery]$ ./rq -n -q "p d/,/ | s switch(comparenum(@level,0),1,'+','')+pad('-',@level-1)+id+':'+firstname+' '+lastname+'('+root(id)+':'+root(firstname)+' '+root(lastname)+')' | h k:id;p:managerid" samples/organization.csv
    1:John A(1:John A)
    +12:Winsor D(1:John A)
    +-85:Jerry C(1:John A)
    +--16:Smith H(1:John A)
    +-108:Tom B(1:John A)
    100:Ray G(100:Ray G)
    +22:Albert B(100:Ray G)
    +-21:Linda K(100:Ray G)
    +-17:Robert J(100:Ray G)
    +--35:Lily J(100:Ray G)
    101:Sam A(101:Sam A)
    +105:Liz Z(101:Sam A)