답변:
$ 터치 ./-c $ 'a \ n12 \ tb'foo $ du -hs * 0 12 개 b 0 푸 총 0
당신이 볼 수 있듯이, -c
파일에 옵션으로 찍은 du
및보고되지 않습니다 (당신은 볼 수 total
있기 때문에 라인을 du -c
). 또한라는 a\n12\tb
파일은 a
and 라는 파일이 있다고 생각하게합니다 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
누락되었습니다.
GNU
ls 와 같은 일부 도구 ∕
는 출력이 터미널로 갈 때 인쇄 할 수없는 문자를 물음표 (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-z0-9.+-]
.
/tmp
) 또는 고가의 자동차가 많은 지역 ( ) 에 주차하면 $HOME
Q & A 사이트로 이동하는 것이 더 나쁘며 어떤 조건에서든 차를 잠그지 않는 것이 좋습니다 (잠긴 차고, 스크립트) 당신은 어떤 네트워크 또는 이동식 저장 장치에 연결되지 않은 컴퓨터에서만 혼자서 작성했습니다 ...)
"b "
또는 같은 "a\bb"
)는 터미널에서 사용자를 속일 수 있지만의 출력을 구문 분석하는 스크립트는 아닙니다 du ./*
. 아마 그것에 대한 메모를 추가해야합니다. 내일 할거야. 이전에 나는 일반적인 의미로 특권 을 의미 root
했지만 (물론 모든 것에 더 적용됨 root
). 개행은 허용되며 무시하는 것은 버그입니다. 버그는 악용되는 습관이 있습니다. 사례별로 위험을 측정해야합니다. 좋은 코딩 방법은 많은 경우에 문제를 피할 수 있습니다. 확실히 SE에서는 인지도를 높여야합니다.
어떤 파일을 나열할지에 관해서는 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 명령에 인수로 전달 될 때 확장 된 파일 이름이 파일 이름으로 간주되도록 보장하는 데 종종 사용 됩니다.