Insert Tabs / Indent text

Hi,

i need replace the slash (/) with a newline (\n) and a tab (\t).

With 'find -type f' in a folder i got this output:
./1999/01/file1
./1999/01/file2
./1999/02/file1
./2000/04/file1
./2000/04/file2
./2000/04/file3
./2000/04/file4
./2000/06/file1
./2000/06/file2
./2000/06/file3
./2000/06/file4

This is the result what i want to get:

1999
     01
         file1
         file2
     02 
         file1
2000
     04 
         file1
         file2
         file3
         file4
     06
        file1
        file2
        file3
        file4    

I try it with this one liner:

find -type f | tr '\/' '\n' | awk '!x[$0]++'
  • find gives me the output
  • tr removes the slashes with newline
  • awk removes double entries

With this line a got a result like this:
.
1999
01
file1
file2
file3

This is close to that what i want, but i dont know how i indent the code now.

I found this Tree Homepage which looks nice, but dont meet my needs, because i must add various values to each entry.

Could somebody gives me a hint?

Thanks in advance.

Stefano

a slightly different output format, but....
tree.awk:

#! /usr/bin/awk -f

# tree.10
# print nice tree from find(1) output and alike
# Example:
#       find dir | tree.awk

BEGIN{
        FS = "/";
        i = 0;
        while ( i++ <= ARGC )
        {
                if ( ARGV ~ /(-h)|(-\?)/ )
                {
                        print "Usage: tree.awk [FS=field-separator] [file ...]"
                        EXIT=1;
                        exit 1;
                }
        }
}

function fineprint(branches)
{
        gsub(" ","    ", branches);
        gsub("[|]","& ", branches);
        gsub("`","&---", branches);
        gsub("[+]","&---", branches);
        return branches;
}

function mktree(number,branches,   tnumber)
{

        if (number > NR)
        {
                return number - 1;
        }

        tnumber = number;

        while (array["shift", number] < array["shift", tnumber + 1])
        {
                tnumber = mktree(tnumber + 1, branches" ");
                if (tnumber == NR) break;
        }

        if (array["shift", number] == array["shift", tnumber + 1])
        {
                array["slip", number] = branches"+";
        }

        if ((array["shift", number] > array["shift", tnumber + 1]) \
                || tnumber == NR)
        {
                array["slip", number] = branches"`";
        }


        return tnumber;
}

{
        array["shift", NR] = NF;
        array["name", NR] = $(NF);
}

END{
        if (EXIT)
                exit EXIT;

        for (i = 1; i <= NR; i++)
        {
                i = mktree(i, "");
        }

        for (i = 1; i <= NR; i++)
        {

                if (i > 1)
                {
                        lprev = length(array["slip", i - 1]);
                        lcurr = length(array["slip", i]);
                        if (lprev > lcurr - 1)
                                legacy = substr(array["slip", i - 1], 0, \
                                                lcurr - 1);
                        else
                                legacy = array["slip", i-1];
                        tail = substr(array["slip", i], length(legacy) + 1 , \
                                        lcurr - length(legacy));
                        gsub("[+]", "|", legacy);
                        gsub("`", " ", legacy);
                        array["slip", i] = (legacy)(tail);
                }

                printf "%s%s\n", fineprint(array["slip", i]), \
                                array["name", i];

        }
}

Another approach:

find -type f |
awk -F"/" '
a[$2] && $3==a[$2] {print "\t\t" $4}
a[$2] && $3!=a[$2] {a[$2]=$3;print "\t" $3;print "\t\t" $4}
!a[$2]{a[$2]=$3;print $2;print "\t" $3;print "\t\t" $4} '

Use nawk or /usr/xpg4/bin/awk on Solaris.

Regards

yeah, but I'd assume the OP would want a non-static 'depth'....

Thanks to you. I decide me for the second version because its short and works for me.

@vgersh99: This folderstructure has a static depth of three levels

year
  month
    file

Could you explain what awk does, Franklin52?

Stefano

Sure, here we go:

find -type f |
awk -F"/" '
a[$2] && $3==a[$2] {print "\t\t" $4}
a[$2] && $3!=a[$2] {a[$2]=$3;print "\t" $3;print "\t\t" $4}
!a[$2]{a[$2]=$3;print $2;print "\t" $3;print "\t\t" $4} '
awk -F"/" '

Change the fieldseparator to a slash

a[$2] && $3==a[$2] {print "\t\t" $4}

If the element a[$2] of the array exists (not a new year) and the 3th field (number) is equal to the value of the element of the array (not a new number) print 2 tabs before the 4th field (filename)

a[$2] && $3!=a[$2] {a[$2]=$3;print "\t" $3;print "\t\t" $4}

If the element a[$2] of the array exists (not a new year) and the 3th field (number) is not equal to the value of the element of the array (we have a new number!), assign the value of the 3th field (number) to the element a[$2], print 1 one tab before the 3th field (number) and 2 tabs before the 4th field (filename) on separate lines

!a[$2]{a[$2]=$3;print $2;print "\t" $3;print "\t\t" $4} '

If the array a[$2] doesn't exist (we have a new year!) assign the value of the 3th field (number) to the element a[$2], print the 2nd field (year), one tab before the 3th field (number) and 2 tabs before the 4th field (filename) on separate lines

Regards

Ah, thanks Franklin52.

i read a introduction to awk and think i got the most of this code, but i have few question to the arrays.
From where come from, are they filled automaticly like $0 with the whole line? What is in there?

Stefano

A useful link where awk arrays are described:

AWK Language Programming - Arrays in awk

Regards

use strict;
my ($n,$ind,%hash,%hash2)=(1,5);
open FH,"<a.txt";
while(<FH>){
	my @tmp=split("/",$_);
	if (not exists $hash2{$tmp[0]}){
		$hash2{$tmp[0]}->{SEQ}=$n;
		$n++;
	}
	$hash{$tmp[0]}->{$tmp[1]}.=" " x (2*$ind).$tmp[2];
}
close FH;
for my $out_key (sort {$hash2{$a} <=> $hash2{$b} } keys %hash){
	print $out_key,"\n";
	my %h = %{$hash{$out_key}};
	for my $in_key (sort keys %h){
		print " " x $ind;
		print $in_key,"\n";
		print $h{$in_key};
	}
}