[unix] “du-sh *”와“du-sh ./*”의 차이점은 무엇입니까?

차이 무엇 du -sh *du -sh ./*?

참고 : 관심 분야는 *./*부분입니다.



답변

$ 터치 ./-c $ 'a \ n12 \ tb'foo
$ du -hs *
0
12 개 b
0 푸
총 0

당신이 볼 수 있듯이, -c파일에 옵션으로 찍은 du및보고되지 않습니다 (당신은 볼 수 total있기 때문에 라인을 du -c). 또한라는 a\n12\tb파일은 aand 라는 파일이 있다고 생각하게합니다 b.

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

그게 낫다. 적어도 이번에 -c는 옵션으로 사용되지 않습니다.

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

더 좋습니다. ./접두사 방지 -c에서는 옵션의 부재로 취해지고 ./전에 b출력이 전혀 없다 있음을 나타냅니다에서 b거기에 파일하지만, 개행 문자가있는 파일이있다 (그러나 아래 참조 1 가에 대한 자세한 여담을 위해).

./가능 하면 접두사 를 사용하는 것이 좋으며 , 그렇지 않은 경우 임의의 데이터에 대해서는 항상 다음을 사용해야합니다.

cmd -- "$var"

또는:

cmd -- $patterns

경우 cmd지원하지 않는 --옵션의 끝을 표시하려면 (이 선택에 의해 그리고에 대한처럼 문서화 된 경우를 제외하고 저자에 버그로보고해야한다 echo).

./*문제가 해결 --되지 않는 경우가 있습니다 . 예를 들어 :

awk -f file.awk -- *

a=b.txt현재 디렉토리에 호출 된 파일이 있으면 실패합니다 ( 파일 처리 a를 지시하는 b.txt대신 awk 변수 를 설정 ).

awk -f file.awk ./*

./a유효한 awk 변수 이름이 아니기 때문에 문제 가 없으므로 ./a=b.txt변수 할당으로 간주되지 않습니다.

cat -- * | wc -l

stdin에서 읽 -도록 지시 cat하는 것처럼 현재 디렉토리에 호출 된 파일이 있으면 실패합니다 ( -대부분의 텍스트 처리 유틸리티 및 cd/에 특수 함 pushd).

cat ./* | wc -l

./-특별하지 않기 때문에 OK cat입니다.

같은 것들:

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

포함 foo하는 파일 수를 계산하는 것은 파일 이름에 개행 문자가 포함되지 않는다고 가정하기 때문에 잘못되었습니다 ( wc -l개행 문자, grep각 파일 에 대한 출력 및 파일 이름 자체의 수). 대신 사용해야합니다 :

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

/파일 이름 당 하나만있을 수 있으므로 문자 수를 계산하는 것이 더 안정적입니다.

재귀 grep의 경우 동등한 트릭은 다음을 사용하는 것입니다.

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

./* 그래도 원하지 않는 부작용이있을 수 있습니다.

cat ./*

파일 당 두 문자를 더 추가하므로 인수의 최대 크기 + 환경의 한계에 빨리 도달 할 수 있습니다. 때로는 ./출력에보고하기를 원하지 않습니다 . 처럼:

grep foo ./*

출력 :

./a.txt: foobar

대신에:

a.txt: foobar

추가 탈선

1 . 의견에 대한 토론에 따라 여기에서 확장해야한다고 생각합니다.

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

./의 각 파일의 시작 을 표시한다는 것은 각 파일 이름이 시작되는 위치 (at ./)와 끝나는 위치 ( ./출력 의 다음 또는 끝 이전 줄 바꿈)를 명확하게 식별 할 수 있음을 의미 합니다.

그 의미는의 출력과 du ./*는 반대로 du -- *스크립트에서 쉽게 출력되지는 않지만 안정적으로 구문 분석 될 수 있다는 것입니다.

출력이 터미널로 갈 때 파일 이름이 당신을 속일 수있는 더 많은 방법이 있습니다.

  • 제어 문자, 이스케이프 시퀀스는 표시 방법에 영향을 줄 수 있습니다. 예를 들어, \r커서를 줄의 시작 부분으로 \b이동하고 커서를 뒤로, \e[C앞으로 (대부분의 터미널에서) 뒤로 이동합니다 .
  • 터미널에서 많은 문자가 가장 분명한 문자 인 공백 문자로 시작하여 보이지 않습니다.
  • 대부분의 글꼴에서 슬래시와 동일하게 보이는 유니 코드 문자가 있습니다.

    $ printf '\u002f \u2044 \u2215 \u2571 \u29F8\n'
    /    

    (브라우저에서 어떻게 작동하는지 확인하십시오).

예를 들면 :

$ touch x 'x ' $'y\bx' $'x\n0\t.\u2215x' $'y\r0\t.\e[Cx'
$ ln x y
$ du -hs ./*
0       ./x
0       ./x
0       ./x
0       .∕x
0       ./x
0       ./x

의 많은 x있지만 y누락되었습니다.

GNUls 와 같은 일부 도구 는 출력이 터미널로 갈 때 인쇄 할 수없는 문자를 물음표 (U + 2215는 인쇄 가능함)로 바꿉니다. GNU du는 그렇지 않습니다.

그들이 스스로를 드러 낼 수있는 방법이 있습니다 :

$ 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

방법을 참조하십시오 으로 향했다 ???우리가 말한 후에 ls우리의 문자 집합이 ASCII했다.

$ du -hs ./* | LC_ALL=C sed -n l
0\t./x$
0\t./x $
0\t./x$
0\t.\342\210\225x$
0\t./y\r0\t.\033[Cx$
0\t./y\bx$

$줄의 끝을 표시하므로 "x"vs를 확인할 수 있습니다. "x "인쇄 할 수 없는 모든 문자와 비 ASCII 문자는 백 슬래시 시퀀스로 표시됩니다 (백 슬래시 자체는 두 개의 백 슬래시로 표시됨). 그것은 GNU 였고 sed, 모든 POSIX 호환 sed구현 에서 동일해야 하지만 일부 오래된 sed구현은 거의 도움이되지 않습니다.

$ du -hs ./* | cat -vte
0^I./x$
0^I./x $
0^I./x$
0^I.M-bM-^HM-^Ux$

(표준은 아니지만 cat -A일부 구현 에서도 매우 일반적입니다 ). 즉, 하나의 유용하고 다른 표현을 사용하지만, 모호 ( "^I"<TAB>표시 인스턴스에 대해 동일).

$ du -hs ./* | od -vtc
0000000   0  \t   .   /   x  \n   0  \t   .   /   x      \n   0  \t   .
0000020   /   x  \n   0  \t   . 342 210 225   x  \n   0  \t   .   /   y
0000040  \r   0  \t   . 033   [   C   x  \n   0  \t   .   /   y  \b   x
0000060  \n
0000061

그것은 표준적이고 모호하지 않으며 (구현마다 구현에 일관성이 있지만) 읽기 쉽지 않습니다.

당신은 y위에 나타나지 않았다는 것을 알 수 있습니다. 파일 이름 과 관련이 없지만 완전히 관련이없는 문제du -hs * 이지만 주목해야합니다. du디스크 사용을보고 하므로 이미 나열된 파일에 대한 다른 링크를보고하지 않습니다 ( du하드 링크가 나열되어있을 때 모든 구현이 그렇게 동작 하지는 않습니다) 명령 행에서).


답변

어떤 파일을 나열할지에 관해서는 a *와 차이가 없습니다 ./*. 유일한 차이점은 두 번째 형식이며 각 파일 ./앞에는 점 슬래시가 있으며 이는 일반적으로 현재 디렉토리를 의미합니다.

기억 .디렉토리가 현재 디렉토리에 대한 속기 표기법입니다.

$ ls -la | head -4
total 28864
drwx------. 104 saml saml    12288 Jan 23 20:04 .
drwxr-xr-x.   4 root root     4096 Jul  8  2013 ..
-rw-rw-r--.   1 saml saml      972 Oct  6 20:26 abcdefg

echo쉘이 무엇을 확장 시키는 지보기 위해이 두리스트가 본질적으로 같은 것임을 확신 할 수 있습니다 .

$ echo *
$ echo ./*

이 두 명령은 현재 디렉토리의 모든 파일을 나열합니다.

다음과 같이 가짜 데이터를 만들 수 있습니다.

$ touch file{1..5}
$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file1
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file2
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file3
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file4
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file5

위의 echo명령 을 사용 하면 다음과 같은 출력이 나타납니다.

$ echo *
file1 file2 file3 file4 file5
$ echo ./*
./file1 ./file2 ./file3 ./file4 ./file5

이 차이는 불필요하게 보일 수 있지만 명령 줄을 통해 파일 이름을 파일 이름으로 전달하는 다양한 유닉스 명령 줄 도구를 보장하려는 상황이 있습니다!

그렇다면 왜 ./*를 사용합니까?

스테판의 대답은 지적 @ 때문에 유닉스의 파일 및 디렉토리의 이름을 지정할 때 문자가 법적 무엇의 특성으로 위험한 파일 이름은 명령 줄에서 다양한 유닉스 명령에 전달 할 때 예상치 못한 부작용이있는 구성 할 수있다.

따라서 ./다양한 Unix 명령에 인수로 전달 될 때 확장 된 파일 이름이 파일 이름으로 간주되도록 보장하는 데 종종 사용 됩니다.


답변