ls -d가 파일을 나열하는 이유와 문서는 어디에 있습니까?


48
  • 지정할 때로 ls --directory a*시작하는 디렉토리 만 나열해야합니다.a*
  • 그러나 파일과 디렉토리로 시작합니다. a

질문 :

  • 어디보다 다른이에 대한 몇 가지 문서를 찾을 수 maninfo내가 생각하는 어디 철저하게 보였다?
  • 이것은 BASH에서만 작동합니까?


5
echo a*또한 시작 파일 a(있는 경우)을 나열합니다 . ls이 일을 하지 않고 bash를하고 있음을 더 명확하게하기 위해 .
ash108

답변:


89

a**a*구문은하지에 의해, 쉘에 의해 구현되는 ls명령.

입력 할 때

ls a*

쉘 프롬프트에서 쉘 a*은 이름이로 시작하는 현재 디렉토리의 모든 기존 파일 목록으로 확장 됩니다 a. 예를 들어, a*시퀀스로 확장 하고 a1 a2 a3인수로 인수로 전달할 수 ls있습니다. ls명령 자체 결코는보고 *문자를; 단지 세 개의 인수 a1a2, 및을 볼 수 a3있습니다.

와일드 카드 확장을 위해 "파일"은 현재 디렉토리의 모든 엔티티를 나타냅니다. 예를 들어, a1일반 파일 일 a2수도 있고 디렉토리 일 a3수도 있고 심볼릭 링크 일 수도 있습니다. 그것들은 모두 디렉토리 엔트리를 가지고 있으며, 쉘의 와일드 카드 확장은 해당 엔트리가 어떤 종류의 엔티티를 참조하는지 상관하지 않습니다.

실제로 모든 쉘 (bash, sh, ksh, zsh, csh, tcsh 등)은 와일드 카드를 구현합니다. 세부 사항은 다를 수 있지만 *0 개 이상의 문자를 ?일치 시키고 단일 문자 를 일치 시키는 기본 구문 은 상당히 일관성이 있습니다.

특히 bash의 경우 bash 매뉴얼의 "파일 이름 확장"섹션에 설명되어 있습니다. info bash"파일 이름 확장"을 실행 하고 검색하거나 여기를 참조 하십시오 .

이것은 개별 명령이 아니라 쉘에 의해 수행된다는 사실은 몇 가지 흥미로운 (때로는 놀라운) 결과를 가져옵니다. 이에 대한 가장 좋은 점은 와일드 카드 처리가 모든 명령에 대해 (거의) 일관성이 있다는 것입니다 . 만약 쉘이 이것을하지 않았다면 필연적으로 어떤 명령들은 귀찮게하지 않을 것이고, 다른 것들은 저자가 "더 나은"것으로 생각한 미묘하게 다른 방식으로 그것을 할 것입니다. (Windows 명령 셸 에이 문제가 있다고 생각하지만 더 이상 언급 할 수는 없습니다.)

반면에 여러 파일의 이름을 바꾸는 명령을 작성하는 것은 어렵습니다. 당신이 쓰는 경우 :

mv *.log *.log.bak

*.log.bak현재 디렉토리에 이미 존재하는 파일을 기반으로 확장 되었기 때문에 실패했을 것입니다 . 이런 종류의 작업을 수행하는 명령이 있지만 파일의 이름을 바꾸는 방법을 지정하려면 고유 구문을 사용해야합니다. 와 같은 일부 명령 find은 자체 와일드 카드 확장을 수행 할 수 있습니다. 쉘의 확장을 억제하기 위해 인수를 인용해야합니다.

find . -name '*.txt' -print

쉘의 와일드 카드 확장은 전적으로 명령 행 인수의 구문과 기존 파일 세트를 기반으로합니다. 그것은 할 수없는 명령의 의미에 의해 영향을받을. 예를 들어, 모든 .log파일을 상위 디렉토리 로 이동 하려면 다음을 입력하십시오.

mv *.log ..

당신이 잊어 버린 경우 ..:

mv *.log

.log현재 디렉토리에 정확히 두 개의 파일이 있으면 다음과 같이 확장됩니다.

mv one.log two.log

이름이 one.log바뀌고 클로버가 two.log됩니다.

편집 : 그리고 52 upvotes, 수락 및 전문가 배지 후, 실제로 제목의 질문에 대답해야합니다.

-d또는 --directory옵션은하는 ls디렉토리 만 나열하도록 지시하지 않습니다. 디렉토리는 내용이 아닌 그대로 디렉토리를 나열하도록 지시합니다. 디렉토리 이름을에 인수로 지정 ls하면 기본적으로 디렉토리 의 내용 이 나열 됩니다. 일반적으로 관심있는 항목 -d이므로 디렉토리 자체 만 나열하도록합니다. 와일드 카드와 결합 할 때 특히 유용합니다. 입력하면 :

ls -l a*

ls이름이로 시작하는 각 파일 과 이름이로 시작되는 각 디렉토리 a내용 을 길게 나열 합니다 a. 파일과 디렉토리 목록을 원하는 경우 각각 한 줄씩 사용할 수 있습니다.

ls -ld a*

이는 다음과 같습니다.

ls -l -d a*

ls명령이 *문자를 보지 못한다는 것을 다시 기억하십시오 .

이것이 문서화 된 곳은 거의 모든 유닉스 계열 시스템 man ls에서 ls명령에 대한 문서를 보여줍니다 . 대부분의 Linux 기반 시스템 ls에서이 명령은 GNU coreutils 패키지의 일부입니다. 당신이있는 경우에 info명령을 하나 info ls또는 info coreutils ls더 많은 최종적이고 포괄적 인 문서를 제공해야합니다. MacOS와 같은 다른 시스템은 다른 버전의 ls명령을 사용할 수 있으며 명령이 없을 수 있습니다 info. 해당 시스템의 경우을 사용하십시오 man ls. 그리고 ls --help쇼됩니다 상대적으로 짧은 사용법 메시지 (내 시스템에 117 선) 된 경우 는 GNU의로 coreutils 구현을 사용하고 있습니다.

그렇습니다. 전문가조차도 문서를 참고해야합니다. 이 고전적인 농담을 참조하십시오 .


8
@Thomas : 이름이로 시작 하는 현재 디렉토리a* 의 모든 파일 목록으로 확장됩니다 . a
키이스 톰슨

2
@Thomas : 또는 지정한 디렉토리에 :ls subdir/a*
Keith Thompson

1
셸 확장 후에 실행 된 명령을 실제로 보려면 명령 echo입니다. 당신이 할 때 무슨 일이 일어나고 있는지 알고 싶다면 ls a*, 먼저 실행echo ls a*
Carlos Campderrós

1
아니면 그냥 echo a*... 쉘은 어쨌든 확장을 수행합니다
쓸모없는

2
@sendmoreinfo : 쉘과 설정에 따라 다릅니다. csh 및 tcsh에서 실패한 글로브 확장은 오류입니다. bash shopt -s failglob에서 동일한 동작이 발생합니다. 예를 들어, 설정 nullglob하지 않지만 빈 문자열로 확장됩니다. failglob*nosuchfile*
키이스 톰슨

27

Keith Thompson의 답변을 참조하십시오. 그러나 ls --directory a*파일 디렉토리를 표시 하는 이유를 설명하려면 :이 --directory옵션은 디렉토리가 아닌 파일을 억제하지 않습니다. 대신 디렉토리를 그대로 나열하고 내용을 나열합니다. 예:

$ mkdir foo
$ touch foo/bar
$ ls foo
bar
$ ls --directory foo
foo

3
이 예는 -F옵션에 더욱 매력적입니다.
glenn jackman

6

매우 명확하게하기 위해, ls (1) 매뉴얼 페이지에 문서화되어 있습니다 :

-d, --directory 는 내용 대신 디렉토리 항목을 나열하고 기호 링크를 역 참조하지 않습니다.

공정하게 말하면, "컨텐츠 대신 엔트리"는 아마도 더 설명적일 수 있습니다 :

FILE이 디렉토리 인 경우 해당 디렉토리의 내용을 나열하는 대신 디렉토리 항목 자체를 표시하십시오. FILE이 기호 링크 인 경우 링크가 가리키는 파일 대신 링크 항목 자체를 표시하십시오.


설명서 페이지에서 -d 옵션을 설명 할 수 있지만 (요약 한 경우) 인수 확장 및 와일드 카드는 쉘에서 수행되므로 ls 매뉴얼 페이지에 문서화되어 있지 않습니다. 셸에서 파일 이름 확장을 해제하면 "ls a *"는 문자 그대로 'a *'라는 파일 만 표시합니다.
Johnny

다른 응답자들이 쉘 확장에 응답 한 것은 놀랍게도, 그 중 어느 것도 소박한 설명과 그것이 어떻게 잘못 판독 될 수 있는지를 다루지 않습니다. 이미 잘 알려진 내용을 반복해서 말씀해 주시려면보다 직접적으로 말씀해주십시오.
msw

4

글 로빙

설명했듯이 Unix 전문 용어에서는 *확장 (및 유사한 확장)을 glob빙 (bing )이라고하며 일반적으로 명령 프로세서의 기능입니다 (Unix 용어에서는 "쉘"이라고 함). 따라서 다른 많은 곳에서도 globbing을 사용할 수 있습니다. 입력 man 7 glob고전적인 리눅스 배포판의 쉘에서 (또는 볼 )에 대한 자세한을 위해 glob빙.

초기 유닉스에서 glob실제로 구현 된 별도의 프로그램 이라고합니다 /etc/glob(10 페이지 참조 이 오래된 UNIX 설명서를 그에 대한 문서에 대한). 요즘은 코드 라이브러리에서 제공하는 코드 루틴이며 일반적으로 쉘에서 사용됩니다. 출처 : Wikipedia .

디렉토리

ls -d디렉토리뿐만 아니라 파일을 나열 하는 이유에 관해서 는 ...

ls매뉴얼 페이지 이런 일이 발생하는 이유하지만 아주 간결한 설명과 함께 설명합니다. 다음은 확장 된 설명에 대한 시도입니다.

기본적 으로 디렉토리 이름이 주어지면 디렉토리 ls내용 이 나열 되며 디렉토리에 대한 심볼릭 링크 에 대해 동일한 작업을 수행합니다 . 이 -d옵션은 "디렉토리 이름 (들)이 주어진 경우"( bing에 의해 암시 적 으로 주어질 수도 있음 glob)을 의미하며, 디렉토리의 _name_s 만 표시하고 내용은 표시 하지 않습니다 . 마찬가지로, 디렉토리에 대한 심볼릭 링크의 이름 (명시 적 또는 암시 적 )을 제공 하는 경우 참조하는 디렉토리의 내용이 아닌 심볼릭 링크의 파일 이름을 표시하십시오.

-d옵션은 아무 상관이없는, 지금까지의 내가 함께 말할 수 있는 항목이 나열되어 있습니다; (출처 :이 수행 할 수 있습니다 여기 와) find과 같이, : find . -maxdepth 1 -type d. GNU로만 그렇게하는 좋은 방법이 있는지 확실하지 않습니다 ls. 다음find명령 사용법에 대한 몇 가지 예입니다 .

요약하자면, 기본적으로 ls경로 이름이 주어지면 디렉토리의 내용이 표시됩니다. -d표준 파일에서와 같이 디렉토리 이름 자체 만 표시하여이 동작을 변경합니다.


3

문서 는 디렉토리 이름 만 수신 할 때 디렉토리 항목 나열한다고 말하지 않으며 내용 대신ls 디렉토리 항목을 나열 합니다. 이해하는 가장 좋은 방법은 다음과 같습니다.

> {ice} ~ :10:47 % ls -l / 
total 97
drwxr-xr-x   2 root root  4096 May  3 00:27 bin
drwxr-xr-x   4 root root  1024 May  3 14:17 boot
drwxr-xr-x   2 root root  4096 Apr 29 13:44 cdrom
drwxr-xr-x  18 root root  4420 May  9 09:58 dev
...
lrwxrwxrwx   1 root root    33 May  3 14:16 vmlinuz -> boot/vmlinuz-3.9.0-030900-generic
lrwxrwxrwx   1 root root    29 May  3 11:07 vmlinuz.old -> boot/vmlinuz-3.8.0-19-generic
> {ice} ~ :10:47 % ls -ld /
drwxr-xr-x 25 root root 4096 May  3 14:16 /

2

문서는 쉘의 일부입니다 . 특히 셸은 명령을 실행하기 전에 특정 순서로 다양한 확장 및 대체 를 수행합니다.

Bourne 호환 쉘단어 확장 순서 는 다음과 같습니다.

  1. 물결 확장
  2. 파라미터 확장
  3. 명령 대체
  4. 산술 확장
  5. 필드 분할
  6. 경로명 확장
  7. 견적 제거

따라서 ls명령은 *문자를 볼 수 없으며 인수는 a*glob 패턴 과 일치하는 모든 파일로 이미 확장되었습니다 . 파일 이름 globbing이 필요한 각 명령이이 기능 자체를 구현해야하는 Windows와는 다릅니다.


1

필요한 키워드 ( man bash)는 "Pathname Expansion"입니다.


3
"경로 확장"또는 "파일 이름 생성"과 비슷합니다. "패턴 일치"와 관련되어 있지만 동일하지는 않습니다.
Stéphane Chazelas

@StephaneChazelas 실제로 "패턴 일치"는 매뉴얼 페이지에서 "경로 확장"의 하위 섹션 인 반면 "파일 이름 생성"은 (정보 문서에서만) 전혀 발생하지 않습니다.
Hauke ​​Laging
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.