GNU/Linux >> Tutoriels Linux >  >> Linux

La différence entre "du -sh *" et "du -sh ./*" ?

Quelle est la différence entre du -sh * et du -sh ./* ?

Remarque :Ce qui m'intéresse, c'est le * et ./* pièces.

Réponse acceptée :

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

Comme vous pouvez le voir, le -c le fichier a été pris en option pour du et n'est pas signalé (et vous voyez le total ligne à cause de du -c ). Aussi, le fichier nommé an12tb nous fait penser qu'il existe des fichiers appelés a et b .

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

C'est mieux. Au moins cette fois -c n'est pas considéré comme une option.

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

C'est même mieux. Le ./ le préfixe empêche -c d'être pris en option et l'absence de ./ avant b dans la sortie indique qu'il n'y a pas de b fichier là-dedans, mais il y a un fichier avec un caractère de nouvelle ligne (mais voir ci-dessous pour d'autres digressions à ce sujet).

Il est recommandé d'utiliser le ./ préfixe si possible, et sinon et pour des données arbitraires, vous devriez toujours utiliser :

cmd -- "$var"

ou :

cmd -- $patterns

Si cmd ne prend pas en charge -- pour marquer la fin des options, il faut le signaler comme bogue à son auteur (sauf quand c'est par choix et documenté comme pour echo ).

Il y a des cas où ./* résout les problèmes qui -- n'a pas. Par exemple :

awk -f file.awk -- *

échoue s'il existe un fichier nommé a=b.txt dans le répertoire courant (définit la variable awk a vers b.txt au lieu de lui dire de traiter le fichier).

awk -f file.awk ./*

N'a pas le problème car ./a n'est pas un nom de variable awk valide, donc ./a=b.txt n'est pas considéré comme une affectation de variable.

cat -- * | wc -l

échoue s'il existe un fichier appelé - dans le répertoire courant, comme cela indique cat lire depuis son stdin (- est spécial pour la plupart des utilitaires de traitement de texte et pour cd /pushd ).

cat ./* | wc -l

est OK car ./- n'est pas spécial pour cat .

Des choses comme :

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

pour compter le nombre de fichiers contenant foo sont erronés car ils supposent que les noms de fichiers ne contiennent pas de caractères de nouvelle ligne (wc -l compte les caractères de saut de ligne, ceux générés par grep pour chaque fichier et ceux dans les noms de fichiers eux-mêmes). Vous devriez utiliser à la place :

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

(en comptant le nombre de / caractères est plus fiable car il ne peut y en avoir qu'un par nom de fichier).

Pour grep récursif , l'astuce équivalente consiste à utiliser :

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

./* peut cependant avoir des effets secondaires indésirables.

cat ./*

ajoute deux caractères supplémentaires par fichier, ce qui vous ferait atteindre plus tôt la limite de la taille maximale des arguments + environnement. Et parfois, vous ne voulez pas que ./ à signaler dans la sortie. Comme :

grep foo ./*

Renvoie :

./a.txt: foobar

au lieu de :

a.txt: foobar

Digressions supplémentaires

. J'ai l'impression que je dois développer cela ici, suite à la discussion dans les commentaires.

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

Ci-dessus, ce ./ marquer le début de chaque fichier signifie que nous pouvons clairement identifier où chaque nom de fichier commence (à ./ ) et où il se termine (à la nouvelle ligne avant le prochain ./ ou la fin de la sortie).

Connexe :Comment ajouter le sous-répertoire bin du premier répertoire de GOPATH à PATH ?

Cela signifie que la sortie de du ./* , contrairement à celle de du -- * ) peut être analysé de manière fiable, mais pas aussi facilement dans un script.

Cependant, lorsque la sortie est envoyée à un terminal, il existe de nombreuses autres façons dont un nom de fichier peut vous tromper :

  • Les caractères de contrôle, les séquences d'échappement peuvent affecter la façon dont les choses sont affichées. Par exemple, r déplace le curseur au début de la ligne, b déplace le curseur vers l'arrière, e[C vers l'avant (dans la plupart des terminaux)…

  • de nombreux caractères sont invisibles sur un terminal en commençant par le plus évident :le caractère espace.

  • Certains caractères Unicode ressemblent exactement à la barre oblique dans la plupart des polices

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

(voir comment ça se passe dans votre navigateur).

Un exemple :

$ 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

Beaucoup de x ‘s mais y est manquant.

Certains outils comme GNU ls remplacerait les caractères non imprimables par un point d'interrogation (notez que (U+2215) est cependant imprimable) lorsque la sortie va à un terminal. GNU du pas.

Il existe des moyens de les faire se révéler :

$ 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

Découvrez comment tourné vers ??? après avoir dit ls que notre jeu de caractères était ASCII.

$ du -hs ./* | LC_ALL=C sed -n l0t./x$0t./x $0t./x$0t.342210225x$0t./yr0t.
Linux
  1. Linux :Différence entre /dev/console , /dev/tty et /dev/tty0 ?

  2. Différence entre 2>&-, 2>/dev/null, |&, &>/dev/null et>/dev/null 2>&1 ?

  3. Quelle est la différence entre Sudo Su - et Sudo Su - ?

  4. La différence entre /opt et /usr/local ?

  5. La différence entre les liens symboliques et les liens matériels ?

La différence entre plus, moins et la plupart des commandes

La différence entre '$ . Foo' Et '$ ./foo' ? ?

La Différence Entre Nss Et Pam?

Différence entre /bin et /usr/bin

Quelle est la différence entre /tmp et /run ?

Quelle est la différence entre unlink et rm ?