Как использование тильды работает как ярлык для моего домашнего каталога?

30

Я был в замешательстве, пытаясь скопировать некоторые файлы с одного компьютера на другой. Я понял это, но синтаксис все еще смущает меня. Это работает:

scp ~/Desktop/Volenteer.png jay@server.ip:~j0h/b

который кладет Volenteer.pngв папку /home/j0h/b. Тем не менее, это не работает:

scp ~Desktop/Volenteer.png     jay@server.ip:~j0h/b

Это также дает сбой, давая статус выхода 1 файл не найден:

scp ~/Desktop/Volenteer.png     jay@server.ip:~/j0h/b

Как это сделать:

scp ~Desktop/Volenteer.png     jay@server.ip:~j0h/b

Итак , ясно, есть какая - то разница между ~и ~/ этой разницей наличия/

$~/
bash: /home/j0h/: Is a directory
$ ~
bash: /home/j0h: Is a directory

Так почему же в scp ~решимость ~/? Это предположение, я не могу проверить, что происходит. Но это кажется противоречивым, а потому и запутанным. Это ошибка в scp? или что-то в тильде мне не хватает?

j0h
источник
2
Просто примечание, здесь написано «волонтер», с «и» вместо «е» :)
AER
2
Я либеральный спеллер.
j0h
Связанный вопрос: askubuntu.com/q/972319/295286
Сергей Колодяжный

Ответы:

68

~ это ваш домашний каталог.

~fooявляется домашним каталогом пользователя foo, если такой пользователь существует, или просто каталогом с именем ~foo, если этого пользователя не существует.


Следовательно, в:

scp ~Desktop/Volenteer.png     jay@server.ip:~j0h/b

~Desktopбудет расширяться до домашнего каталога пользователя Desktop, если такой пользователь существует (и обычно его нет), или будет просто ~Desktop(путь, который обычно не существует).


В:

scp ~/Desktop/Volenteer.png     jay@server.ip:~/j0h/b

~/j0hразвернется в каталог с именем j0hв jayдомашнем каталоге, который, опять же, вряд ли существует.


Дело не в том ~и ~/где разница возникает, а в ~и ~foo.


Кроме того, ~может также использоваться для навигации по истории каталогов:

  • ~-предыдущий рабочий каталог (вроде $OLDPWD)
  • ~+текущий рабочий каталог (вроде $PWD)

Это не относится к scp, так как вы не можете изменить каталоги в середине scpоперации.

И если вы используете pushdиpopd для поддержки стека каталогов, то и будет каталогом в стеке каталогов, как видно из выходных данных . будет каталогом с конца (начиная с нуля, в обоих случаях). Например:~N~+NNdirs~-NN

$ for i in etc usr var tmp; do pushd /$i; done
/etc ~/.vim
/usr /etc ~/.vim
/var /usr /etc ~/.vim
/tmp /var /usr /etc ~/.vim

$ dirs
/tmp /var /usr /etc ~/.vim

Затем к каталогам в стеке можно получить доступ, используя:

/tmp /var /usr /etc ~/.vim
  ~0   ~1   ~2   ~3     ~4
 ~+0  ~+1  ~+2  ~+3    ~+4
 ~-4  ~-3  ~-2  ~-1    ~-0 
  ~+   ~-
Мур
источник
Итак, ~+всегда эквивалентно .тогда, правильно? Кажется излишним.
Wildcard
1
@ Уайлдкарт хорошо, не совсем. ~+и ~-использовать значения $PWDи $OLDPWD, которые являются абсолютными путями. .всегда относительный путь. Итак, если есть команда, которая изменяет текущий рабочий каталог при выполнении, она увидит новый путь, для .которого путь, расширенный, ~-останется прежним. tar -Cэто пример, хотя я признаю, что не могу придумать, как его использовать ~+. $PWDбудет так же хорошо, за исключением того, что вам не нужно заключать в кавычки, ~+/foo/barесли $PWDсодержит пробелы.
Муру
1
Спасибо, это проясняет. На самом деле это хороший пример использования прямо здесь: некоторые команды отказываются работать с относительными путями по соображениям безопасности; с такими командами вы не можете использовать, ./filenameно можете использовать "$PWD/filename"или более просто ~+/filename. (И некоторые команды будут работать с относительными путями, но есть функциональные различия, такие как lnили tar.)
Wildcard
21

Прочитайте документацию по GNU для Bash Tilde Expansion (как я должен был сделать до моей первой итерации этого ответа).

~/Desktopи ~j0hделают принципиально разные вещи, что объясняет, почему ~Desktopне работает:

  • Обычная переменная ~заменяет текущую $HOMEпеременную среды, установленную при входе в систему. Так ~разрешается /home/oliдля меня, и ~/Desktopчитается как /home/oli/Desktop. Здесь вы видите, что тильда используется чаще всего.

  • ~usernameразрешает в дом этого пользователя , как установлено в /etc/passwd. Так ~oliрешает /home/oli, ~j0hможет решить, /home/j0hно не обязательно, ваш homedir может быть где угодно.

  • ~not-a-usernameне разрешается Потому Desktopчто не пользователь, ~Desktopне подставляется. Он воспринимается буквально как файл или путь с именем ~Desktop(которого здесь нет).

И само собой разумеется, все это происходит удаленно (было бы бесполезно, scpесли бы его заменили локальными значениями). Это работает, потому что Bash не заменит, ~...если ему предшествует что-либо кроме пробела.

Оли
источник
Что getent passwd binговорит?
Муру
2
«bin» - системный пользователь на большинстве компьютеров с Linux, с домашним каталогом / bin.
fNek
1
Неспособность развернуть ~dirсогласуется с документацией GNU: «... символы в префиксе тильды, следующие за тильдой, рассматриваются как возможное имя для входа ... Если имя для входа неверное или расширение тильды не удается, слово оставлен без изменений. " Здесь dirнет имени пользователя в этой системе, поэтому оно остается без изменений.
Апсиллер
Спасибо всем. Наверное, мне следует прочитать ссылки, которые я публикую :)
Oli
4

Символ ~используется в качестве ярлыка для /home/userin bash, поэтому в случае ~/Desktop/Volenteer.pngнего это сокращение для /home/user/Desktop/Volenteer.png.

Итак, как вы можете видеть /, как всегда, показывает новый уровень в иерархии файловой системы.

Марк Кирби
источник
3
только половина права, это сокращение для переменной окружения $ HOME. ~{user}/может быть любым произвольным путем, заданным файлом базы данных passwd (5). Хотя да, стандарты filesytem.org размещают обычных пользователей в / home, это не относится к каждому пользователю (т. Е. Root в / root и сервисы в / var / ... или более ранних версиях с использованием / usr вместо / home)
Дуайт Спенсер
DwightSpencer правильно. Я поддерживаю несколько серверов, где пользователи находятся в / usr / {CLIENTNAME} / home / и совместно используются несколькими внутренними и удаленными системами (все указывают на этот каталог), поэтому необходимо поддерживать только одну систему. И ~ указывает на этот каталог;)
Rinzwind
3
@ Rinzwind eek. Я должен протестовать против этого кощунственного злоупотребления /usr.
Муру
@muru эй, это был не МОЙ звонок>: - D Это было от ШОС D:
Rinzwind
1
Честно говоря, мне понравилось использование / usr для всех вещей пользователя, поскольку это то, что он изначально имел в виду. То, что я нахожу в эти дни, - это более кощунственное неправильное использование / usr / bin как великого унифицированного хранилища всех двоичных файлов (sys, user, sysop) за пределами базовых binutils. В конце концов, / usr был задуман как все, к чему у пользователей есть доступ, извлеченный из монтирования nfs, в то время как / usr / local был локальным пользовательским пространством с / sbin в качестве двоичных файлов sysop и системных / bin файлов Я понимаю, что / home может быть другим разделом, но может / usr / home / ... хранить его в / usr и сохранять его как пространство имен пользователя как в политике, так и в реализации и образе мышления.
Дуайт Спенсер
3

~является сокращением для переменной среды $HOMEна большинстве производных оболочек c / поддерживающих POSIX-совместимых оболочек. наиболее часто используется для ~ссылки на свой собственный домашний каталог или каталог другого пользователя:

cd ~ # ie shell, take me to my home folder

cd ~root # i.e. shell, take me to root's home folder

Чтобы найти домашний каталог для любого локального пользователя в системе POSIX (UNIX, Linux, OS X, BSD), использующей базу данных passwd (5), запустите awk /etc/passwdследующим образом:

awk -F: '{ print $1,$(NF-1) }' /etc/passwd

Это перечислит каждого локального пользователя и его домашний каталог.

Дуайт Спенсер
источник