'ls'와 'echo $ (ls)'의 차이점


27

두 개의 쉘 샘플을 고려하십시오

$ ls
myDoc.html
SomeDirectory
someDoc.txt

$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt

첫 번째 ls는 내가 이해하는 것처럼 현재 작업 디렉토리의 내용을 stdout파일에 추가합니다 (터미널이 표시하는 것). 이 올바른지?

두 번째는 ls명령 의 값 (현재 작업 디렉토리의 내용)을 가져 와서 stdout파일로 인쇄 합니다. 이 올바른지?

두 명령이 서로 다른 출력을주는 이유는 무엇입니까?


1
에코를하고 있기 때문입니다. echo 명령에 대한 입력으로 ls의 출력.
ankidaemon

이것은 "예상 된"행동이며, 누군가가 곧 설명 할 것입니다. 그러나 ls자체적으로 한 줄에 여러 항목을 제공하지 않습니까?
roaima

@roaima columnized ls는 bsd "feature"의 잔해입니다. 유닉스 버전은 한 줄에 하나의 항목 인쇄
스티브 콕스

@SteveCox 초기 SVR4 이후로 적절한 UNIX를 사용하지 않아서 메모리가 흐릿합니다. 상기시켜 주셔서 감사합니다.
roaima

왜 안돼 echo *?
jdh8

답변:


70

이 명령을 실행할 때 :

ls

터미널은의 출력을 표시합니다 ls.

이 명령을 실행할 때 :

echo $(ls)

쉘은 출력을 캡처하고 워드 분할$(ls)수행 합니다. 기본값을 사용하면 줄 바꿈 문자를 포함하여 모든 공백 문자 시퀀스가 단일 공백으로 바뀝니다. 이것이 출력이 한 줄 에 나타나는 이유 입니다.IFSecho $(ls)

단어 분리에 대한 고급 설명은 Greg의 FAQ를 참조하십시오 .

단어 분리 억제

쉘은 따옴표로 묶인 문자열에서 단어 분리를 수행하지 않습니다. 따라서 다음을 사용하여 단어 분할을 억제하고 여러 줄 출력을 유지할 수 있습니다.

echo "$(ls)"

ls 멀티 라인 출력

ls한 줄에 여러 파일을 인쇄 하는 경우가 있습니다.

$ ls
file1  file2  file3  file4  file5  file6

출력이 ls터미널 로 갈 때의 기본값 입니다. 출력이 터미널로 직접 이동하지 않는 경우 ls기본값은 한 줄에 하나의 파일로 변경됩니다.

$ echo "$(ls)"
file1
file2
file3
file4
file5
file6

이 동작은에 설명되어 man ls있습니다.

또 다른 미묘함 : 명령 대체 및 후행 줄 바꿈

$(...)명령 치환 및 출력으로부터 개행 문자 후행 쉘 제거합니다 명령 대체 . 기본적 echo으로 출력 끝에 새 줄 하나를 추가 하기 때문에 일반적으로 눈에 띄지 않습니다 . 따라서 끝에서 하나의 줄 바꿈을 잃고에서 하나 $(...)를 얻는다면 echo아무런 변화가 없습니다. 그러나 명령의 출력이 2 개 이상의 줄 바꾸기 문자로 끝나고 echo하나만 다시 추가하면 출력에 하나 이상의 줄 바꿈 이 누락됩니다. 예를 들어, printf후행 줄 바꿈 문자를 생성 하는 데 사용할 수 있습니다 . 줄 바꿈 수가 다르더라도 다음 명령은 모두 하나의 빈 줄을 출력하는 것과 같습니다.

$ echo "$(printf "\n")"

$ echo "$(printf "\n\n\n\n\n")"

$ 

이 동작은에 설명되어 man bash있습니다.

또 다른 놀라움 : 경로 이름 확장, 두 번

세 개의 파일을 만들어 봅시다 :

$ touch 'file?' file1 file2

차이 관찰 ls file?echo $(ls file?):

$ ls file?
file?  file1  file2
$ echo $(ls file?)
file? file1 file2 file1 file2

의 경우에 echo $(ls file?), 파일 글로브는 file?팽창 파일명이 발생 file1하고 file2출력에 두번 나타나는. Jeffiekins가 지적했듯이 경로 이름 확장 은 셸에서 먼저 ls실행 된 다음 다시 실행 되기 전에 수행 되기 때문 echo입니다.

큰 따옴표를 사용하면 두 번째 경로 이름 확장 을 억제 할 수 있습니다.

$ echo "$(ls file?)"
file?
file1
file2

4
또한 isattystdout이 tty인지 확인할 수 있습니다. ls는이를 사용하여 색상 사용 여부를 결정합니다.
야누스 Troelsen

1
마지막 코드 스 니펫에서 따옴표가 일치하지 않습니까? 또는 $( )실제로 구문 장벽을 제공하여 보간 할 필요가 없습니까?
고양이

6
@cat $()은 구문 장벽을 제공합니다.
Random832

2
한 가지 더 중요한 차이점 : 파일 이름에 와일드 카드 문자가 포함되어 있으면 echo명령이 와일드 카드확장합니다 . 예를 들어, 파일을ls 반환 하면 ? file1 file2 이면 파일echo $(ls) 을 반환 합니까? file1 file2 file1 file2 .
Jeffiekins

1
@Jeffiekins echo는 와일드 카드를 확장하지 않습니다. 쉘은 결과 확장을 인수로 전달하기 전에 수행합니다 echo.
chepner

0

ls 출력을 터미널로 보내고 있는지 인식합니다.

ls명령 프롬프트에서 실행 하면 pseudo-tty에 씁니다. 의 출력을 재지 정하는 것은 ls일반적으로 의사 -tty로 진행 되지 않으며ls 출력을 다르게 형식화합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.