GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Der Unterschied zwischen „du -sh *“ und „du -sh ./*“?

Was ist der Unterschied zwischen du -sh * und du -sh ./* ?

Hinweis:Was mich interessiert, ist der * und ./* Teile.

Akzeptierte Antwort:

$ touch ./-c $'an12tb' foo
$ du -hs *
0       a
12      b
0       foo
0       total

Wie Sie sehen können, ist der -c Datei wurde als Option zu du genommen und wird nicht gemeldet (und Sie sehen die total). Zeile wegen du -c ). Auch die Datei namens an12tb lässt uns glauben, dass es Dateien namens a gibt und b .

$ du -hs -- *
0       a
12      b
0       -c
0       foo

Das ist besser. Zumindest diesmal -c wird nicht als Option genommen.

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

Das ist sogar noch besser. Der ./ Präfix verhindert -c nicht als Option genommen werden und das Fehlen von ./ vor b in der Ausgabe gibt an, dass kein b vorhanden ist Datei darin, aber es gibt eine Datei mit einem Zeilenumbruchzeichen (aber siehe unten für weitere Abschweifungen dazu).

Es hat sich bewährt, ./ zu verwenden Präfix wenn möglich, und wenn nicht und für beliebige Daten, sollten Sie immer verwenden:

cmd -- "$var"

oder:

cmd -- $patterns

Wenn cmd unterstützt -- nicht Um das Ende der Optionen zu markieren, sollten Sie es dem Autor als Fehler melden (außer wenn es freiwillig und dokumentiert ist wie für echo ).

Es gibt Fälle, in denen ./* löst Probleme, die -- nicht. Zum Beispiel:

awk -f file.awk -- *

schlägt fehl, wenn es eine Datei namens a=b.txt gibt im aktuellen Verzeichnis (setzt die awk-Variable a zu b.txt anstatt ihm zu sagen, dass es die Datei verarbeiten soll).

awk -f file.awk ./*

Hat das Problem nicht, weil ./a ist kein gültiger awk-Variablenname, also ./a=b.txt wird nicht als Variablenzuweisung genommen.

cat -- * | wc -l

schlägt fehl, wenn es eine Datei namens - gibt im aktuellen Verzeichnis, wie das cat mitteilt aus seiner stdin zu lesen (- ist speziell für die meisten Textverarbeitungsprogramme und für cd /pushd ).

cat ./* | wc -l

ist in Ordnung, weil ./- ist nichts Besonderes für cat .

Dinge wie:

grep -l -- foo *.txt | wc -l

um die Anzahl der Dateien zu zählen, die foo enthalten sind falsch, weil davon ausgegangen wird, dass Dateinamen keine Zeilenumbrüche enthalten (wc -l zählt die Newline-Zeichen, die von grep ausgegeben werden für jede Datei und die in den Dateinamen selbst). Sie sollten stattdessen verwenden:

grep -l foo ./*.txt | grep -c /

(Zählen der Anzahl von / Zeichen ist zuverlässiger, da es nur eines pro Dateiname geben kann).

Für rekursives grep , ist der entsprechende Trick die Verwendung von:

grep -rl foo .//. | grep -c //

./* kann jedoch einige unerwünschte Nebenwirkungen haben.

cat ./*

fügt zwei weitere Zeichen pro Datei hinzu, sodass Sie die Grenze der maximalen Größe von arguments+environment früher erreichen würden. Und manchmal möchten Sie diesen ./ nicht in der Ausgabe gemeldet werden. Wie:

grep foo ./*

Würde ausgeben:

./a.txt: foobar

statt:

a.txt: foobar

Weitere Abschweifungen

. Ich habe das Gefühl, dass ich das hier weiter ausführen muss, wenn ich der Diskussion in den Kommentaren folge.

$ du -hs ./*
0       ./a
12      b
0       ./-c
0       ./foo

Oben, dieser ./ Das Markieren des Anfangs jeder Datei bedeutet, dass wir klar erkennen können, wo jeder Dateiname beginnt (bei ./ ) und wo es endet (beim Zeilenumbruch vor dem nächsten ./ oder das Ende der Ausgabe).

Verwandte:Wie füge ich das bin-Unterverzeichnis des ersten Verzeichnisses in GOPATH zu PATH hinzu?

Das bedeutet, dass die Ausgabe von du ./* , im Gegensatz zu du -- * ) kann zuverlässig geparst werden, wenn auch nicht so einfach in einem Skript.

Wenn die Ausgabe jedoch an ein Terminal geht, gibt es noch viel mehr Möglichkeiten, wie ein Dateiname Sie täuschen kann:

  • Steuerzeichen und Escape-Sequenzen können die Darstellung beeinflussen. Zum Beispiel r bewegt den Cursor zum Anfang der Zeile, b bewegt den Cursor zurück, e[C weiterleiten (in den meisten Terminals)…

  • Viele Zeichen sind auf einem Terminal unsichtbar, beginnend mit dem offensichtlichsten:dem Leerzeichen.

  • Es gibt Unicode-Zeichen, die genauso aussehen wie der Schrägstrich in den meisten Schriftarten

     $ printf 'u002f u2044 u2215 u2571 u29F8n'
     / ⁄ ∕ ╱ ⧸
    

(Sehen Sie, wie es in Ihrem Browser läuft).

Ein Beispiel:

$ touch x 'x ' $'ybx' $'xn0t.u2215x' $'yr0t.e[Cx'
$ ln x y
$ du -hs ./*
0       ./x
0       ./x
0       ./x
0       .∕x
0       ./x
0       ./x

Viele x ist aber y fehlt.

Einige Tools wie GNU ls würde die nicht druckbaren Zeichen durch ein Fragezeichen ersetzen (beachten Sie, dass (U+2215) ist jedoch druckbar), wenn die Ausgabe an ein Terminal geht. GNU du nicht.

Es gibt Möglichkeiten, sie sich offenbaren zu lassen:

$ ls
x  x   x?0?.∕x  y  y?0?.?[Cx  y?x
$ LC_ALL=C ls
x  x?0?.???x  x   y  y?x  y?0?.?[Cx

Siehe wie wurde zu ??? nachdem wir ls gesagt haben dass unser Zeichensatz ASCII war.

$ du -hs ./* | LC_ALL=C sed -n l0t./x$0t./x $0t./x$0t.342210225x$0t./yr0t.
Linux
  1. Der Unterschied zwischen Sourcing (‚.‘ oder ‚source‘) und dem Ausführen einer Datei in Bash?

  2. Linux:Unterschied zwischen /dev/console , /dev/tty und /dev/tty0?

  3. Was ist der Unterschied zwischen Sudo Su – und Sudo Su –?

  4. Der Unterschied zwischen symbolischen und harten Links?

  5. Der Unterschied zwischen „$ . Foo‘ und ‚$ ./foo‘??

Der Unterschied zwischen mehr, weniger und den meisten Befehlen

Der Unterschied zwischen /opt und /usr/local?

Der Unterschied zwischen .exrc und .vimrc?

Unterschied zwischen /etc/crontab und crontab -e

Unterschied zwischen /bin und /usr/bin

Unterschied zwischen Gerätedatei und Gerätetreibern