경로의 접두사로 사용될 때 ~ (물결표)는 무엇입니까?


11

편집 : 이것은 /programming/998626/meaning-of-tilde-in-linux-bash-not-home-directory/ 의 복제본입니다 . 이 질문을 중복으로 끝내는 것으로 유명하지 않습니다.

나는 ~홈 디렉토리에서와 같이 말하는 것이 아니라 오히려 이것을 참조한다.

$ ls ~foo/bar
/some/mount/point/foo/bar

그러나 다른 마운트 포인트로 시도하면 다음과 같습니다.

$ mount | ag "/dev "
devfs on /dev (devfs, local, nobrowse)
$ ls /dev/stdin
/dev/stdin
$ ls ~stdin
zsh: no such user or named directory: stdin . 
# bash has a similar error message: 
ls: ~stdin: No such file or directory

~이 맥락에서 무엇이 부름입니까? 어떻게 작동합니까?

편집 : 아래의 의견 중 일부에 대한 자세한 내용 :

  1. foo내 시스템의 사용자 이름이 아님을 증명할 수 있습니다 .
  2. 자동 완성을 시도 할 때 ls -lah ~모든 옵션이 표시되지는 않습니다. 즉 , 자동 완성에 표시되지 않는 cd ~qux경우 할 수 qux있습니다. 다시 한 번 qux내 시스템의 사용자가 아닙니다.
  3. 중요한 /some/mount/point것은 네트워크 공유입니다.
  4. 모든 세부 사항은 경로 이름 확장의 Z 쉘 기능인 일부 이름이 지정된 경로 muckery를 제안하지만 이것은 Z 쉘의 이름 지정된 경로와 같은 것을 지원하지 않는 bash에서도 작동합니다.

5
~foo사용자의 홈 디렉토리입니다 foo. 사용자를 지정하지 않으면 현재 사용자가 기본값입니다.
DopeGhoti

그러나이 경우 /some/mount/point분명히 내 홈 디렉토리가 아닙니다. cd ~저를 필요 /Users/$username/실현합니다 경기$HOME
RD

1
zsh물결표를 사용하여 명명 된 디렉토리를 나타내는 것으로 나타납니다.
DopeGhoti

나도 그것을 의심했다!! 어떤 이유로 든 위에서 언급 한 일련의 명령은 bash에서도 작동합니다 ( bash -c "ls ~foo/bar")-이름이 지정된 디렉토리는 없습니다. 또한 zsh 내에서도를 검사하면 env명명 된 디렉토리가 설정되어 있지 않습니다. Mac OS를 사용 중이며 이것이 OS X에만 해당되는 기능이라고 생각합니다.
RD

1
당신은 단지 말했다 ~foo. 실제 문자열 (예는 foo아님)을 가져 와서 수행하십시오 grep "actual username" /etc/passwd. bash 매뉴얼에 따라 가능한 로그인 사용자 이름 ~text에서만 작동해야합니다 ( 예를 들어 시스템 사용자의 경우 실제로 로그인 할 수 있음을 의미하지는 않습니다 ). 모든 테스트에서 사용자 이름 과 일치 합니다. ~lp~stringstring
Sergiy Kolodyazhnyy

답변:


14

~ foo는 무엇입니까

bash 매뉴얼 에서 인용 (추가 강조) :

단어가 인용 부호없는 물결표 문자 (`~ ')로 시작하면, 인용되지 않은 첫 번째 슬래시 (또는 인용 부호가없는 슬래시가없는 모든 문자) 앞에 오는 모든 문자는 물결표 접두어로 간주됩니다. 물결표 접두어가 인용되면 물결표 뒤에 물결표 접두어 문자가 가능한 로그인 이름 으로 처리됩니다 .

~foofoo지정된대로 정확하게 사용자의 홈 디렉토리로 확장됩니다 /etc/passwd. 여기에는 시스템 사용자 이름이 포함될 수 있습니다. 반드시 인간 사용자를 의미하거나 실제로 로컬로 로그인 할 수있는 것은 아닙니다 (예 : SSH 키를 통해 로그인 할 수 있음).

에서 언급 한 바와 같이 사실, 의견 , bash사용 getpwnam기능. 이 기능 자체는 POSIX 표준에 의해 지정 되므로 macOS X를 포함한 대부분의 유닉스 계열 시스템에 존재해야합니다 . 이 기능은 /etc/passwdLDAP 및 NIS와 같은 다른 데이터베이스에만 국한되지 않고 검색합니다. 394 행에서 시작하는 bash 소스 코드 , tilde.c파일 에서 발췌 한 내용 :

  /* No preexpansion hook, or the preexpansion hook failed.  Look in the
     password database. */
  dirname = (char *)NULL;
#if defined (HAVE_GETPWNAM)
  user_entry = getpwnam (username);
#else
  user_entry = 0;

실제 예

아래는 내 시스템에서 시스템 사용자 이름으로 테스트 한 것을 볼 수 있습니다. 해당 passwd항목 및 결과에주의ls ~username

$ grep '_apt' /etc/passwd
_apt:x:104:65534::/nonexistent:/bin/false
$ ls ~_apt
ls: cannot access '/nonexistent': No such file or directory
$ grep '^lp' /etc/passwd
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
$ ls ~lp
ls: cannot access '/var/spool/lpd': No such file or directory

예를 들어 _apt계정이 출력에 의해 제안 된대로 잠겨 있더라도 passwd -S apt가능한 로그인 이름으로 여전히 표시됩니다.

_apt L 11/29/2017 0 99999 7 -1

참고 : 이것은 macOS 전용 기능이 아니라 셸 전용 기능입니다.


쉘이 계정 만료 날짜 또는 물결표를 확장 할 때 잠겨 있거나 기타 항목을 찾는 데 의존 할 수는 없습니다. 예를 들어 Linux에서 만료 날짜는 /etc/shadow비밀번호와 같은 다른 보호 된 인증 정보와 함께에 저장됩니다 . 참조 passwd는 암호를 유효하지 않게 만드는 것입니다. 다른 방법으로는 인증을 방해하지 않습니다.
ilkkachu

@ilkkachu 네, 맞습니다. testuser암호 만료 날짜 를 추가 하고 수정 하여 테스트했습니다 . 사용자 이름은 여전히 ​​탭 완성에 나타납니다. 답변에서 그 비트를 제거했습니다
Sergiy Kolodyazhnyy

1
이 답변의 유일한 문제는 bash맨 페이지를 인용한다는 것입니다 (그리고 오래된 페이지 는 인용 된 것 같습니다). OP는 실제로 사용 중입니다 zsh(더 명확 할 수 있음).하지만 의견 bash에서 같은 행동을 한다고 언급되어 있습니다.
Ken Wayne VanderLinde

2
@Abigail이 언급 한 네트워크 기반 디렉토리 서비스를 포함하여 쉘과 동일한 조회 메커니즘을 따르는 getent passwd foo대신 사용할 수 있습니다 grep foo /etc/password.
RJHunter

1
내 경우에는 올바른 LDAP 및 NIS와 같은 비트에 대한 답변으로 수락되었습니다!
RD

5

에 대한 정보가 표시되는 이유를 요약하면 홈 디렉토리에 폴더가있는 시스템에 ~foo/bar이름이 지정된 사용자가 있기 때문 입니다.foobar

왜 (물결표) 가 단순한 "홈 디렉토리"이상 인지 설명하는 다른 커뮤니티에서이 솔루션을 참조하십시오 ~.

bin시스템에 사용자 이름이 지정된 경우 다음 명령 으로 bin 홈 디렉토리의 내용을 나열 할 수 있습니다 .

ls ~bin

시도 할 수있는 또 다른 방법은 프롬프트에서 다음을 입력 한 후 탭 완성을 사용하는 것입니다 (캐리지 리턴하지 말고 탭 키를 사용하십시오).

ls -lah ~ tab

~계속하면 확장 될 사용자의 홈 디렉토리 목록을 볼 수 있습니다. 탭 완성의 예 (잘린) 출력ls -lah ~ tab

$ ls -lah ~ [tab]
~antman/            ~games/
~bin/               ~mail/

1
탭 완성 +1 이것은 bash가 가능한 로그인 이름을 얻을 수있는 모든 사용자 이름을 명확하게 나타냅니다 /etc/passwd. 물론 사용자가 시스템에서 가지고있는 사용자 이름을 알고 있다면 무슨 일이 일어나고 있는지 명확하게 알 수 있습니다.
Sergiy Kolodyazhnyy

2
bash 완성에 대한 팁에 감사드립니다. 몇 가지 흥미로운 자동 완성 결과가 나타났습니다. ~foo자동 완성을 수행 하는 동안 foo내 시스템의 사용자가 아니며 실제로는 존재하지 않는다는 것을 증명할 수 있습니다 /etc/passwd. 또한 모든 폴더 / 파일 /some/mount/point이 자동 완성 에 표시되므로 매우 흥미 롭습니다.
RD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.