Сделать результат pwd в терминах «~»?

28

pwd дает мне

/data/users/me/some/random/folder

Есть ли простой способ получения

~/some/random/folder

от pwd?

Sibbs Gambling
источник
Является ли использование через sed вариант?
Мэтью Д. Скоулфилд
7
Если вы собираетесь это сделать, я настоятельно рекомендую назвать получившуюся команду чем-то другим pwd. В противном случае вы нарушите сценарии, которые ожидают использовать его вывод в контекстах, которые не выполняют раскрытие тильды.
Чарльз Даффи

Ответы:

25

Если вы используете bash, то dirsвстроенный режим имеет желаемое поведение:

dirs +0
~/some/random/folder

(Примечание +0, нет-0 .)

С zsh:

dirs
~/some/random/folder

Чтобы быть точным, нам сначала нужно очистить стек каталогов, иначе dirsбудет напечатано все содержимое:

dirs -c; dirs

Или с zsh«S printвстроенной командой:

print -rD $PWD

или

print -P %~

(это включает быстрое расширение . %~in $PS1расширяет текущий каталог с $HOMEзаменой на, ~но также обрабатывает другие именованные каталоги, такие как домашний каталог других пользователей или именованные каталоги, которые вы определяете сами).

хаос
источник
Я все время переключаюсь между bash и zsh. К сожалению, это решение заставляет меня помнить разницу между снарядами, а также помнить (проверять), где я сейчас нахожусь. Ответ @Bichoy для этих двоих не зависит от оболочки.
AVP
18

Вы можете использовать функцию замены подстроки Bash:

$ pwd
/home/vagrant/foo/bar
$ echo ${PWD/#$HOME/'~'}
~/foo/bar
Nykakin
источник
2
Это также работает в kshи zsh.
mr.spuratic
1
Хотя я и проголосовал за этот ответ, потому что это самый простой способ, здесь есть небольшая оговорка: внутри / tmp / home / username это вернет / tmp ~. Я не могу найти способ вставить знак каретки перед $ HOME, чтобы это исправить. Если вам нужно, чтобы ваше решение было идеальным, не используйте это ...
0
1
@ user18151, чем вы указали на это. Я заменил свой ответ на ${string/#substring/replacement}версию, чтобы предотвратить это поведение.
Nykakin
1
@ mr.spuratic это только правильно (за исключением использования echo) в zsh. В других оболочках, $HOMEбудет рассматриваться как шаблон, и все это может быть разделено + glob.
Стефан Шазелас
Избежать тильды ('~') удалось. Обратите внимание, что \ ~ также работает. Это удобно, когда уже в '-контексте: например,PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Atafar
7

Использование sed:

pwd | sed "s|^$HOME|~|"

Идея состоит в том, чтобы использовать любой символ, который с меньшей вероятностью появляется в пути к домашней директории, в качестве разделителя в sedрегулярном выражении. В приведенном выше примере я использую |.

Хорошая вещь об этой технике - то, что она фактически независима от оболочки.

Вы также можете использовать псевдоним pwdдля /bin/pwd | sed "s|$HOME|~|"получения этого поведения в других сценариях, которые могут быть использованы pwd.

Bichoy
источник
2
Вы должны включить ^якорь в свое регулярное выражение. В противном случае это возможно (хотя и маловероятно) для замены сегмента в середине пути.
Сильдорет
На самом деле регулярное выражение должно выглядеть следующим образом "s|^/home/user\(/.*\)\?$|~\1|". В противном случае он соответствует пути других пользователей , если их имена, как user1, user2, user3и вы подходите простоuser
AVP
3
tilde=\~${PWD#~}

Я думаю, это то, что вы хотите?

Что приятно в тильде, так это когда она развернута в виде шаблона, который не нуждается в цитировании. Использование $HOMEтаким же образом без кавычек приведет к непредсказуемым результатам, потому что любой из его составляющих символов может быть символом шаблона, и поэтому он не всегда может отображать ожидаемый результат.

Но расширение тильды определенно всегда должно происходить так, как если бы оно было результатом цитируемого расширения, и поэтому его результаты предсказуемы. Похоже, что это справедливо практически для каждой оболочки, которую я тестировал как для caseшаблонов, так и для шаблонов параметров, с заметными исключениями обоих ksh93и mkshпо любым причинам - ни один из которых, кажется, не учитывает цитируемый аспект тильды в этом качестве.

Еще одна полезная вещь - это то, что вы можете переопределить $HOMEобработку любого каталога одинаково. Например:

cd ~
HOME=/some/prefix/I/would/like/to/trim 
#or, perhaps more usefully, some scripted means of arriving at same
tilde=\~${OLDPWD#~}
HOME=$PWD

Вот еще один пример:

set 1 2 3 4 5 \~
cd ~; cd -; HOME= IFS=/
for d do shift
      HOME=${*#~/}/$d
      set ~ "$d" $HOME
done; cd -; HOME=$PWD
printf %s\\n "$@"
5/4/3/2/1/2/3/4/5/~/1/2/3/4/5/~
~
5
4
3
2
1
2
3
4
5
~
1
2
3
4
5
~
mikeserv
источник
1
Это действительно интересный подход. Но это предполагает, что $PWDпод $HOME. Вы можете использовать ту же идею в сочетании с заменой шаблона, чтобы сделать его более общим. Как дела ${PWD/#~/\~}?
Микель
1
На самом деле ответ Никакина в основном таков.
Микель
0

Вы можете попробовать заменить ненужную деталь на sed:

pwd | sed 's,^/data/users/me,~,'

или даже лучше:

pwd | sed "s,^$HOME,~,"
user1403360
источник
1
Вам необходимо использовать ^привязку, чтобы обеспечить замену только совпадений в начале пути к каталогу. Кроме того, вам не нужно использовать, gпотому что команда должна заменить максимум 1 вхождение.
Сильдорет
Спасибо. Я все еще учусь этим вещам, а ты комментируешь действительно полезно.
user1403360
Проблематично, если мой домашний каталог /home/aliceи текущий каталог /home/aliceinchains. Но если единственный раз, когда я захочу использовать эту функцию, это когда я знаю, что я - мой домашний каталог или одна из его подкаталогов, тогда она должна работать.
Михай Данила