displaying 3 directory listings in 3 separate columns.

i having problems figuring out how to 'read' in 3 different directory listings and then display them on the screen into 3 separate columns.

i thought i could use a 'for' loop to grab each directory and then assign a unique variable to each line 'read' in.

of course, as you experts all know, you can't do env$num=$env.

an example of the script i had in mind is below.

#!/bin/ksh
num=0
for env in `ls /mg_apps/crm` `ls /mg_apps/ifid` `ls /mg_apps/riab`
do
env$num=$env
num=`expr $num + 1`
done

echo "crm" "ifid" "riab"
echo $env1 $env4 $env7
echo $env2 $env5 $env8
echo $env3 $env6 $env9

however, this method, even if it did work, also has it's own problems - what happens when a new directory is created? it would throw the variable numbering out and i'd get a 'crm' directory appearing in the 'ifid' column.

all solutions greatly appreciated, i love to see diversity, it increases my knowledge of unix.

cheers.

ls /mg_apps/crm > /crm_fl
ls /mg_apps/ifid > /fd_fl
ls /mg_apps/riab > /iab_fl
paste /crm_fl /fd_fl /iab_fl

thanks for that. it works, but i didn't want to mess about with creating files and then deleting them.

i also then have to figure out how to get a title at the top of each column and then display in lovely straight lines.

e.g.

crm ifid

crmuat1 ifiduat
crmproduction ifiduat2
crmuat2 ifiddev

actually that hasn't quite displayed correctly. imagine all the columns are lined up.

With bash/ksh93:

set crm ifid riab
{  printf "%s\t" "$@";printf "\n";eval paste $(printf "<(ls %s) " "$@");}

thank you radoulov, but still not quite what i was after.

once i've placed the full path name of crm, ifid or riab in the 'set' command, i get the full path name as a heading, which is a little messy.

it's also still not aligned in nice straight columns. see the output below.

e.g.

/mg_apps/crm /mg_apps/ifid /mg_apps/riab
crm_MKS_build ifiddev dev
crmdev ifidprd prod
crmprd ifiduat uat
crmuat
reladmin

{  printf "%s\t" "${@##*/}";printf "\n";eval paste $(printf "<(ls %s) " "$@");}

"${@##*/}": bad substitution

I said bash/ksh93!

Something like the following should get you started:

$ touch dir_1/file_{1,2,3,4,5}
$ touch dir_2/newfile_{a,b,c,d,e,f,g}
$ touch dir_3/another_file_{one,two,three,four}
$ cat 3cols.sh
#!/bin/bash

DIR1="dir_1"
DIR2="dir_2"
DIR3="dir_3"

paste -d';' <( ls ${DIR1} ) <( ls ${DIR2} ) <( ls ${DIR3} ) | while read LINE; do
   FILE1=$( echo "${LINE}" | cut -d';' -f1 )
   FILE2=$( echo "${LINE}" | cut -d';' -f2 )
   FILE3=$( echo "${LINE}" | cut -d';' -f3 )
   printf "%-20s\t%-20s\t%-20s\n" "${FILE1:- }" "${FILE2:- }" "${FILE3:- }"
done

exit 0
$ chmod +x ./3cols.sh 
$ ./3cols.sh 
file_1                  newfile_a               another_file_four   
file_2                  newfile_b               another_file_one    
file_3                  newfile_c               another_file_three  
file_4                  newfile_d               another_file_two    
file_5                  newfile_e                                   
                        newfile_f                                   
                        newfile_g                                   

Cheers
ZB

Let me try - this is my first script - so please be lenient!

I used tmp-files and I think it's not good, probably rs can do the trick. But this script is working. It takes names of directories as arguments (there may be more than 3 arguments) and prints the names of files conlumnwise.

#!/bin/sh

for i in $*
do
echo $i > my_temp_file_$i
ls $i >> my_temp_file_$i
echo my_temp_file_$i >> list_of_temp_files
done

pr -m -l 2 `cat list_of_temp_files`

for i in $*
do
rm my_temp_file_$i
done

rm list_of_temp_files

With bash/ksh93:

set /mg_apps/crm /mg_apps/ifid /mg_apps/riab 
{  printf "%-24s" "${@##*/}";printf "\n";eval pr -ml2 $(printf "<(ls %s) " "$@");}

radoulov - thank you, but up until you added the substition "${@##*/}"; your command worked. we only have 'ksh' here and not 'bash/ksh93'.

phystech846 - thank you, but your attempt uses temp files and i was trying to avoid creating files - i find it a bit messy. nice effort though.

Zazzybob - perfect, works a treat - everything lines up nice and straight. thank you. i'm using your attempt, with an extra 'prinf' line for the column titles. see below.

$ cat sol3.ksh
#!/bin/ksh
DIR1="/mg_apps/crm"
DIR2="/mg_apps/ifid"
DIR3="/mg_apps/riab"

printf "%-20s\t%-20s\t%-20s\n" "crm" "ifid" "riab"
echo ""
paste -d';' <( ls ${DIR1} ) <( ls ${DIR2} ) <( ls ${DIR3} ) | while read LINE; do
FILE1=$( echo "${LINE}" | cut -d';' -f1 )
FILE2=$( echo "${LINE}" | cut -d';' -f2 )
FILE3=$( echo "${LINE}" | cut -d';' -f3 )
printf "%-20s\t%-20s\t%-20s\n" "${FILE1:- }" "${FILE2:- }" "${FILE3:- }"
done

I'm not sure this works with ksh93 though :slight_smile:
You seem to have ksh93 (process substitution is not available in ksh88).

This will also work in perl.

#!/usr/bin/perl

$DIR1 ="dir_1";
$DIR2 ="dir_2";
$DIR3 ="dir_3";
@dir1 = `ls -1 $DIR1`;
@dir2 = `ls -1 $DIR2`;
@dir3 = `ls -1 $DIR3`;

$maxFile = scalar(@dir1);
if($maxFile < scalar(@dir2)){
        $maxFile = scalar(@dir2);
}
if($maxFile < scalar(@dir3)){
        $maxFile = scalar(@dir3);
}
        printf("%20s\t%20s\t%20s\n","$DIR1", "$DIR2", "$DIR3");
        for($i=0;$i<$maxFile;$i++)
        {
        printf("%20s\t%20s\t%20s\n","@dir1[$i]", "@dir2[$i]", "@dir3[$i]");
        }

Thanks,
Mukund Ranjan

thanks munkund ranjan. coincedently i'm going to convert the script i'm writing into perl - once i've learnt the language that is.

If you have Python, here's an alternative

#!/usr/bin/python
import os
a = os.listdir("/test1")
b = os.listdir("/test2")
c = os.listdir("/test3")
for item in map(None,a,b,c):
     if item[0] == None: item[0] = ''     
     if item[1] == None: item[1] = ''
     if item[2] == None: item[2] = ''
     print "%20s\t%20s\t%20s" % (item[0],item[1],item[2])