Если вы собираетесь это сделать, я настоятельно рекомендую назвать получившуюся команду чем-то другим pwd. В противном случае вы нарушите сценарии, которые ожидают использовать его вывод в контекстах, которые не выполняют раскрытие тильды.
Чарльз Даффи
Ответы:
25
Если вы используете bash, то dirsвстроенный режим имеет желаемое поведение:
Чтобы быть точным, нам сначала нужно очистить стек каталогов, иначе dirsбудет напечатано все содержимое:
dirs -c; dirs
Или с zsh«S printвстроенной командой:
print -rD $PWD
или
print -P %~
(это включает быстрое расширение . %~in $PS1расширяет текущий каталог с $HOMEзаменой на, ~но также обрабатывает другие именованные каталоги, такие как домашний каталог других пользователей или именованные каталоги, которые вы определяете сами).
Я все время переключаюсь между bash и zsh. К сожалению, это решение заставляет меня помнить разницу между снарядами, а также помнить (проверять), где я сейчас нахожусь. Ответ @Bichoy для этих двоих не зависит от оболочки.
AVP
18
Вы можете использовать функцию замены подстроки Bash:
Хотя я и проголосовал за этот ответ, потому что это самый простой способ, здесь есть небольшая оговорка: внутри / 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.
Вы должны включить ^якорь в свое регулярное выражение. В противном случае это возможно (хотя и маловероятно) для замены сегмента в середине пути.
Сильдорет
На самом деле регулярное выражение должно выглядеть следующим образом "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
~
Это действительно интересный подход. Но это предполагает, что $PWDпод $HOME. Вы можете использовать ту же идею в сочетании с заменой шаблона, чтобы сделать его более общим. Как дела ${PWD/#~/\~}?
Микель
1
На самом деле ответ Никакина в основном таков.
Микель
0
Вы можете попробовать заменить ненужную деталь на sed:
Вам необходимо использовать ^привязку, чтобы обеспечить замену только совпадений в начале пути к каталогу. Кроме того, вам не нужно использовать, gпотому что команда должна заменить максимум 1 вхождение.
Сильдорет
Спасибо. Я все еще учусь этим вещам, а ты комментируешь действительно полезно.
user1403360
Проблематично, если мой домашний каталог /home/aliceи текущий каталог /home/aliceinchains. Но если единственный раз, когда я захочу использовать эту функцию, это когда я знаю, что я - мой домашний каталог или одна из его подкаталогов, тогда она должна работать.
pwd
. В противном случае вы нарушите сценарии, которые ожидают использовать его вывод в контекстах, которые не выполняют раскрытие тильды.Ответы:
Если вы используете bash, то
dirs
встроенный режим имеет желаемое поведение:(Примечание
+0
, нет-0
.)С
zsh
:Чтобы быть точным, нам сначала нужно очистить стек каталогов, иначе
dirs
будет напечатано все содержимое:Или с
zsh
«Sprint
встроенной командой:или
(это включает быстрое расширение .
%~
in$PS1
расширяет текущий каталог с$HOME
заменой на,~
но также обрабатывает другие именованные каталоги, такие как домашний каталог других пользователей или именованные каталоги, которые вы определяете сами).источник
Вы можете использовать функцию замены подстроки Bash:
источник
ksh
иzsh
.${string/#substring/replacement}
версию, чтобы предотвратить это поведение.echo
) вzsh
. В других оболочках,$HOME
будет рассматриваться как шаблон, и все это может быть разделено + glob.PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Использование
sed
:Идея состоит в том, чтобы использовать любой символ, который с меньшей вероятностью появляется в пути к домашней директории, в качестве разделителя в
sed
регулярном выражении. В приведенном выше примере я использую|
.Хорошая вещь об этой технике - то, что она фактически независима от оболочки.
Вы также можете использовать псевдоним
pwd
для/bin/pwd | sed "s|$HOME|~|"
получения этого поведения в других сценариях, которые могут быть использованыpwd
.источник
^
якорь в свое регулярное выражение. В противном случае это возможно (хотя и маловероятно) для замены сегмента в середине пути."s|^/home/user\(/.*\)\?$|~\1|"
. В противном случае он соответствует пути других пользователей , если их имена, какuser1
,user2
,user3
и вы подходите простоuser
Я думаю, это то, что вы хотите?
Что приятно в тильде, так это когда она развернута в виде шаблона, который не нуждается в цитировании. Использование
$HOME
таким же образом без кавычек приведет к непредсказуемым результатам, потому что любой из его составляющих символов может быть символом шаблона, и поэтому он не всегда может отображать ожидаемый результат.Но расширение тильды определенно всегда должно происходить так, как если бы оно было результатом цитируемого расширения, и поэтому его результаты предсказуемы. Похоже, что это справедливо практически для каждой оболочки, которую я тестировал как для
case
шаблонов, так и для шаблонов параметров, с заметными исключениями обоихksh93
иmksh
по любым причинам - ни один из которых, кажется, не учитывает цитируемый аспект тильды в этом качестве.Еще одна полезная вещь - это то, что вы можете переопределить
$HOME
обработку любого каталога одинаково. Например:Вот еще один пример:
источник
$PWD
под$HOME
. Вы можете использовать ту же идею в сочетании с заменой шаблона, чтобы сделать его более общим. Как дела${PWD/#~/\~}
?Вы можете попробовать заменить ненужную деталь на
sed
:или даже лучше:
источник
^
привязку, чтобы обеспечить замену только совпадений в начале пути к каталогу. Кроме того, вам не нужно использовать,g
потому что команда должна заменить максимум 1 вхождение./home/alice
и текущий каталог/home/aliceinchains
. Но если единственный раз, когда я захочу использовать эту функцию, это когда я знаю, что я - мой домашний каталог или одна из его подкаталогов, тогда она должна работать.