Sida 1 av 1

Skillnaden mellan ls och du...

Postat: 22 apr 2008, 22:59
av Osprey
När disken börjar bli full och jag ska kolla var det ligger mest och alltså är mest gynnsamt att rensa så använder jag t.ex du och ls. Då har jag upptäckt att jag får olika resultat och kan inte begripa vad det kommer sig.

Det spelar heller ingen roll om jag tittar på använt utrymme eller allokerat utrymme, inte heller om jag låter ls ta med directories eller inte, du hamnar lite över ändå. Inte mycket, men på c:a 8M utrymme i aktuellt directory så hamnar du c:a 5K över.

Jag har kollat att ls räknar rätt så som jag tänkt mig, men hur tusan räknar du?? ???

Kommandona jag kör är:

Kod: Markera allt

du ../ --max-depth=1 -Sbc | sort --key=1 -i > zd
ls -laF .. | grep -v \/ | awk '{ print $5"\t../"$8 }' | sort --key=1 -i > zl
Som ni ser så har jag också skickat resultatet till två filer som jag sedan har försökt analysera, men jag blir inte klok på vad det är. I källkoden "coreutils" får jag inte heller någon bra uppfattning om det och några symboliska länkar etc. finns inte i mappen där jag kör det...*suck*

Re: Skillnaden mellan ls och du...

Postat: 22 apr 2008, 23:01
av Osprey
Jag kanske var lite otydlig... problemet är alltså att totalsumman för använt utrymme skiljer sig så som jag beskrivit ovan...

Re: Skillnaden mellan ls och du...

Postat: 22 apr 2008, 23:03
av Emil.s
Riktigt mysko. En kort och enkel "proof of concept":

Kod: Markera allt

root@Sandnabba.se: /home/emil #> cat /dev/urandom > tmp_file
^C
root@Sandnabba.se: /home/emil #> 
root@Sandnabba.se: /home/emil #> du tmp_file 
3756	tmp_file
root@Sandnabba.se: /home/emil #> ls -l tmp_file 
-rw------- 1 root root 3842048 2008-04-22 23:01 tmp_file
Ingen aning dock vad som är "fel", om det är någon dvs.

EDIT:
Imponerande första-inlägg lär jag säga. Välkommen till forumet! :)

Re: Skillnaden mellan ls och du...

Postat: 22 apr 2008, 23:12
av Lars
Tillåt mig citera info coreutils "du invocation"
`--apparent-size'
Print apparent sizes, rather than disk usage. The apparent size
of a file is the number of bytes reported by `wc -c' on regular
files, or more generally, `ls -l --block-size=1' or `stat
--format=%s'. For example, a file containing the word `zoo' with
no newline would, of course, have an apparent size of 3. Such a
small file may require anywhere from 0 to 16 KiB or more of disk
space, depending on the type and configuration of the file system
on which the file resides. However, a sparse file created with
this command:

dd bs=1 seek=2GiB if=/dev/null of=big

has an apparent size of 2 GiB, yet on most modern systems, it
actually uses almost no disk space.

Re: Skillnaden mellan ls och du...

Postat: 22 apr 2008, 23:22
av Osprey
Såg förresten att jag inte skickat med helt rätt kod, det jag skickade med var egentligen kommandon som jag använt när jag försökt analysera skillnaden i urval av filer för de två kommandona och där har utskriften av filnamn varit en del av det. Egentligen har jag kört både ls och du från ett c-program när jag fått fram att den märkliga skillnaden finns.

Som synes nedan så har jag kört med --apparent-size och för den delen utan med, plus med och utan olika switchar på båda kommandona för att försöka få dem att ge samma resultat... men på något sätt gåååår inte det... ::)

Kod: Markera allt

lscnt()
{
        int     i;
        char    buf[255];
        FILE    *fp;
        system("ls -laF .. | grep -v / | awk '{ print $5 }' > z");
        i = 0;
        fp = fopen("z","r");
        while(fgets(buf,255,fp) != NULL) ::) 
                i += atoi(buf);
        fclose(fp);
        printf("LS = %d\n",i);
}
ducnt()
{
        printf("DU = ");
        fflush(0);
        system("du --max-depth=0 --apparent-size -Sba ../ | tail -1");
}

Re: Skillnaden mellan ls och du...

Postat: 23 apr 2008, 15:19
av Konservburk
Jag tror du missuppfattat exakt vilka filer som räknas när du använder flaggan -S til du.

Ta din ls-grep-pipeline. Den listar alla filer som inte är kataoger. Sedan tar du ut femte kolumnen med awk och summerar det hela med ett c-program. Jag modifierade den lite så att allt summeras direkt i awk:

Kod: Markera allt

ls -laF | grep -v / | awk '{a+=$5}END{print a}'
Istället för att välja bort kataloger med grep så kan du göra motsvarande med find och xargs:

Kod: Markera allt

find . -maxdepth 1 -not -type d -print0 | xargs -0 ls -l | awk '{a+=$5}END{print a}'
Då väljer find vilka filer som ska summeras och ls -l tar reda på storleken. Du kan såklart låta du -b ta reda på storleken istället, men då ska awk summera första kolumnen och inte femte:

Kod: Markera allt

find . -maxdepth 1 -not -type d -print0 | xargs -0 du -b | awk '{a+=$1}END{print a}'
Då ska du se att ls och du ger samma resultat.

Re: Skillnaden mellan ls och du...

Postat: 23 apr 2008, 16:13
av Osprey
Jag tackar, men det besvarar bara delvis min fråga.

I ditt förslag är det ju find och inte varken ls eller du som väljer vilka filer som ska summeras. Det är möligt att jag inte var helt klar i hur jag beskrev problemt, det var ganska sent när jag skrev inlägget... ^-^

Problemet är alltså egentligen att hur tusan får jag ls (eller egentligen ett program eller vad som helst) att göra samma urval som du gör? Jag får fortfarande ett annat resultat med dina förslag jämfört med du -Sab och det jag vill försöka förstå är hur den gör sina urval, vad -S och -a egentligen innebär i praktiken.

Som jag tolkar dem så innebär -S att den inte tar med storleken på vad som ligger i underdirectoryna, men antagligen storleken på själva directoryfilen och -a innebär egentligen ingenting i det här exemplet eftersom jag här gör tail -1 på utskriften.

Så frågan är egentligen - vad tusan är det som du -S räknar med i summan...?? :)

Re: Skillnaden mellan ls och du...

Postat: 23 apr 2008, 17:15
av Konservburk
Vi tar ett illustrerande exempel:

Kod: Markera allt

$ mkdir du-test
$ cd du-test
$ du -ab
4096    .
En tom katalog är uppenbarligen 4096 byte stor på mitt system.

Kod: Markera allt

$ du -abS
4096    .
Struntar vi att räkna med underkataloger så är den fortfarande lika stor eftersom det inte finns några underkataloger. Låt oss göra en underkatalog:

Kod: Markera allt

$ mkdir a
$ du -ab
4096    ./a
8192    .
$ du -abS
4096    ./a
4096    .
När jag använder -S så räknar den inte med storleken på ./a i den totala summan. Men vad händer om jag gör en fil i underkatalogen?

Kod: Markera allt

$ dd if=/dev/zero of=a/b bs=5904 count=1 2>&-
$ du -ab
5904    ./a/b
10000   ./a
14096   .
$ du -abS
5904    ./a/b
10000   ./a
4096    .
Underkatalogen blir större, men den räknas fortfarande bort när jag använder -S. Vad händer om jag nu gör en fil som inte ligger i underkatalogen?

Kod: Markera allt

$ dd if=/dev/zero of=c bs=5904 count=1 2>&-
$ du -ab
5904    ./c
5904    ./a/b
10000   ./a
20000   .
$ du -abS
5904    ./c
5904    ./a/b
10000   ./a
10000   .
Utan -S ränknas alla filer med i summan, men med -S räknas underkatalegen och filen i den bort. Men hur blir det om man jämför med ls-varianten?

Kod: Markera allt

$ ls -laF | grep -v / | awk '{print$5,$9}'
 
5904 c
Då kommer bara filen c med i summan. Här fattas alltså storleken på själva katalogen som filerna ligger i.

Re: Skillnaden mellan ls och du...

Postat: 23 apr 2008, 20:07
av Osprey
Jo precis, nu börjar jag bli lite klarare och egentligen kan vi glömma ls i det här avseendet, mitt problem är att jag inte begriper hur du räknar. Att jag tog med ls var egentligen lite bara för att kunna förklara problemet.

Det är så att jag har ett program i C, som jag gör opendir(), readdir() etc. och hur jag än summerar stbuf.st_size och/eller stbuf.st_blocks*512 så lyckas jag inte få samma resultat som kommandot du. Jag har provat med att bara summera filer som har flaggan DT_REG (vanliga filer) satt och jag har provat med att summera dem plus de som har DT_DIR (direcories) satt. Med stbuf.st_size får jag ju fram den storlek som filerna använder och med stbuf.st_blocks*512 så får jag ju fram den storlek som är allokerad på disken.

Jag har summerat:
1) Alla DT_REG plus alla DT_DIR, genom att använda mig av stbuf.st_size vilket ger den använda storleken för alla vanliga filer plus directories.
2) Alla DT_REG plus alla DT_DIR, genom att använda mig av stbuf.st_blocks*512 vilket ger den allokerade storleken för alla vanliga filer plus directories.
3) Alla DT_REG, genom att använda mig av stbuf.st_size vilket ger den använda storleken för alla vanliga filer.

Men, jag lyckas inte få fram samma summa som kommandot du ger på något sätt. Symboliska länkar, pipes, blockfiler etc. finns inte i det aktuella directoryt utan det är bara vanliga filer och directories...

Självfallet kan jag lägga ned en dag eller så på att läsa du.c i coreutils och sätta mig in i exakt hur den arbetar, men jag tänkte bara att det kanske fanns någon som kunde komma med ett snabbt enkelt svar...

Tack ändå och kommer du på något bra så mig gärna... :)

Re: Skillnaden mellan ls och du...

Postat: 23 apr 2008, 20:15
av Osprey
Jag får väl lillägga det också, att samma resultat som jag får fram med ls kan jag lätt åstadkomma. Det var därför jag tog det som exempel.

Re: Skillnaden mellan ls och du...

Postat: 23 apr 2008, 23:43
av Konservburk
Jag har iofs inte kollat i coreutils-koden, men jag misstänker att du -b helt enkelt gör en lstat() på varje unik inod och summerar ihop alla st_size den får fram. Om du har med flaggan -S så struntar den helt enkelt i att räkna underkataloger och det som finns i dem. Konstigare än så ska det inte vara.

Hur ser din c-kod ut? Har du tänkt på att en inod kan ha fler än ett filnamn?

Re: Skillnaden mellan ls och du...

Postat: 24 apr 2008, 09:41
av Osprey
Jag var inne och rotade lite i koden (coreutils etc) igår och du kommandot använder inte lstat() vad jag kunde se. Däremot verkar den ha ett klart släktskap med chown och chmod(!), men däremot inte så mycket med ls etc. Vad jag kunde se så använder sig du av något som heter fts (fts.c), som i sin tur verkar använda sig av libcore och en massa annat. Jag var inne och kikade lite i det men lyckades inte hitta något klart svar på hur den arbetar.

Däremot använder sig ls med flera av opendir(), readdir() etc. precis som jag, kanske därför det är så lätt att få samma resultat som de... :)

På något konstigt sätt verkar du lägga till något som inte jag begriper, men för tillfället hinner jag inte ta reda på exakt vad det beror på, jag hamnar tillräckligt nära i alla fall, på samma summa som man får med ls.

Koden kan jag lägga ut lite senare om jag hinner, så kan du också få se den märkliga summeringen...

Re: Skillnaden mellan ls och du...

Postat: 24 apr 2008, 09:53
av Osprey
Konservburk skrev:Har du tänkt på att en inod kan ha fler än ett filnamn?
Jodå, men det är väl främst via symboliska länkar? I min kod summerar jag ju bara DT_REG och i en av summorna även DT_DIR och kommandot du ska väl (-P är satt "by default") inte göra det heller?

Re: Skillnaden mellan ls och du...

Postat: 24 apr 2008, 10:06
av Konservburk
Osprey skrev:
Konservburk skrev:Har du tänkt på att en inod kan ha fler än ett filnamn?
Jodå, men det är väl främst via symboliska länkar? I min kod summerar jag ju bara DT_REG och i en av summorna även DT_DIR och kommandot du ska väl (-P är satt "by default") inte göra det heller?
Symboliska länkar är inte samma sak som att flera filnamn kan peka på samma inod. Jag pratar om hårda länkar. Om du använder flaggan -l till du så räknas varje filnamn även om det finns flera olika som pekar på samma inod. Precis som när du summerar det du får från ls.

Re: Skillnaden mellan ls och du...

Postat: 24 apr 2008, 11:27
av Osprey
Konservburk skrev:Symboliska länkar är inte samma sak som att flera filnamn kan peka på samma inod. Jag pratar om hårda länkar.
Ok helt rätt, det var jag som var lite slarvig i terminologin. Jag tittade efter nu och ln skiljer precis som du säger på symboliska länkar och hårda. Det var jag som inte hade läst den "mansidan" på länge och som hade för mig att alla länkar var symboliska och sedan delades upp i hårda och mjuka. Jag har också ute på företag varit med om att man säger "mjuka länkar" om de som egentligen heter "symboliska".

Men hur som helst så finns det varken symboliska eller hårda länkar i directoryt där jag testar och som jag sa, hade det funnits så borde det inte påverka något ändå. Det är mitt program och du som inte får samma resultat, däremot får mitt program samma resultat som jag får med ls. Som sagt, jag räknar bara DT_REG och DT_DIR och kommandot du har -P satt som standard (default).

Det finns alltså bara DT_REG och DT_DIR i den aktuella mappen (mitt eget $HOME) och ändå får kommandot du ett annat resultat. Jag har provat med att räkna med allt möjligt hit och dit, men har inte lyckats lista ut riktigt hur kommandot du fungerar. Hur som helst så spelar det inte så jättestor roll och om jag bara hade orkat så hade jag ju kunnat ta fillistningen från du och jämföra den med vad jag kan skriva ut från programmet. Det hade då visat vad kommandot du tar med som jag och ls inte tar med. Men som sagt, just nu ids jag inte... :)

Orkar jag/har tid med att göra det så ska jag tala om vad det var som skiljde...

Re: Skillnaden mellan ls och du...

Postat: 24 apr 2008, 15:30
av Konservburk
Osprey skrev:Men hur som helst så finns det varken symboliska eller hårda länkar i directoryt där jag testar och som jag sa, hade det funnits så borde det inte påverka något ändå.
Hårda länkar hade helt säkert påverkat om det funnits några.
Osprey skrev:Det är mitt program och du som inte får samma resultat, däremot får mitt program samma resultat som jag får med ls. Som sagt, jag räknar bara DT_REG och DT_DIR och kommandot du har -P satt som standard (default).
Men nu är det så att -P inte har någonting med hårda länkar att göra. En hård länk ser ut precis som en helt vanlig fil, matchar mot DT_REG osv. Om du vill att du ska räkna som när du summerar med ls så måste du använda flaggan -l, vilken inte är satt som standard. Men är du helt säker på att du inte har några filer med fler än ett filnamn så spelar det såklart ingen roll.
Osprey skrev:Jag var inne och rotade lite i koden (coreutils etc) igår och du kommandot använder inte lstat() vad jag kunde se. Däremot verkar den ha ett klart släktskap med chown och chmod(!), men däremot inte så mycket med ls etc. Vad jag kunde se så använder sig du av något som heter fts (fts.c), som i sin tur verkar använda sig av libcore och en massa annat. Jag var inne och kikade lite i det men lyckades inte hitta något klart svar på hur den arbetar.
Den använder nog det där fts för att effektivt kunna plöja igenom filstrukturen. Du är helt säker på att det inte finns någon lstat() begravd djupt inne i fts-koden?
Osprey skrev:Däremot använder sig ls med flera av opendir(), readdir() etc. precis som jag, kanske därför det är så lätt att få samma resultat som de... :)
Det borde inte vara något problem att summera ihop allting med opendir(), readdir() och lstat(). Jag skrev ett litet c-program som gör just detta, och tro det eller ej, men resultatet blir precis samma som med du (så länge summan får plats i unsigned long):

Kod: Markera allt

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#define skip_subdirs 0x1

unsigned long int du(const char *filename, int flags, int depth)
{
	struct stat st;
	unsigned long size;

	if (lstat(filename, &st))
	{
		return 0;
	}
	size = st.st_size;
	if (S_ISDIR(st.st_mode))
	{
		DIR *d;

		if ((flags & skip_subdirs) && depth > 0)
		{
			return 0;
		}
		if (d = opendir(filename))
		{
			struct dirent *de;

			while (de = readdir(d))
			{
				if (de->d_name[0] != '.' || de->d_name[1] &&
				    (de->d_name[1] != '.' || de->d_name[2]))
				{
					char * s = (char *)malloc(
						strlen(filename) +
						strlen(de->d_name) + 2);
					strcpy(s, filename);
					strcat(s, "/");
					strcat(s, de->d_name);
					size += du(s, flags, depth + 1);
					free(s);
				}
			}
			closedir(d);
		}
	}
	return size;
}

int main(int argc, char *argv[])
{
	printf("du -bls  => %lu\n", du(".", 0, 0));
	printf("du -blsS => %lu\n", du(".", skip_subdirs, 0));

	return 0;
}

Re: Skillnaden mellan ls och du...

Postat: 24 apr 2008, 16:12
av Osprey
Jag tackar så mycket!

Javisst blir det exakt samma resultat som med du. Nu får jag sätta mig och analysera vad det är som skiljer mot mitt pgm och ls, det är något i urvalet av filer som jag gör som inte stämmer.

Det där med hårda länkar och "-P" visste jag iofs, men har inte brytt mig så mycket om det eftersom det inte finns några sådana här nu.

Om jag kommer på det så ska jag tala om vad det är för fel jag har gjort... :)