Зробити pwd результат у терміні "~"?


28

pwd дає мені

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

Чи є простий спосіб отримання

~/some/random/folder

з pwd?


Чи є трубопровід через 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 %~

(Що один виявляється швидке розширення на. %~В $PS1Розкривається в поточному каталозі з $HOMEзамінений , ~а й обробляє інші названі каталоги , як домашній каталог інших користувачів або іменованих каталогів , які ви визначаєте самі).


Я весь час перемикаюся між bash і zsh. На жаль, це рішення змушує мене пам’ятати різницю між оболонками, а також пам’ятати (перевіряти), де я зараз перебуваю. Відповідь від @Bichoy для цих двох оболонок.
AVP

18

Ви можете використовувати функцію заміни змінної підрядки Bash:

$ pwd
/home/vagrant/foo/bar
$ echo ${PWD/#$HOME/'~'}
~/foo/bar

2
Це також працює в kshі zsh.
mr.spuratic

1
Хоча я відповів на цю відповідь, оскільки це найпростіший спосіб, тут є невеликий застереження: всередині / tmp / home / username, це повернеться / tmp ~. Я не можу знайти спосіб вставити знак каретки перед $ HOME, щоб виправити це. Якщо вам потрібно, щоб ваше рішення було ідеальним, не використовуйте це ...
0fnt

1
@ user18151, ніж ви для того, щоб вказати на це. Я замінив свою відповідь на ${string/#substring/replacement}версію, щоб запобігти такій поведінці.
Нікакін

1
@ mr.spuratic це правильно (за винятком використання echo) zsh. В інших оболонках $HOMEрозглядають як зразок, і вся справа підлягає спліт + глобул.
Stéphane Chazelas

Втеча від тильди ('~') зробила трюк. Зверніть увагу, що \ ~ також працює. Це зручно, коли вже в '-контексті: наприклад,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.


2
Потрібно включити ^якір у свій регекс. Інакше для цього можливо (хоча й малоймовірно) замінити відрізок посередині шляху.
Sildoreth

Насправді регулярний вираз повинен виглядати наступним чином "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
~

1
Це дійсно цікавий підхід. Але передбачається, що $PWDпід $HOME. Ви можете використовувати ту саму ідею у поєднанні із заміною візерунка, щоб зробити її загальнішою. Як це ${PWD/#~/\~}?
Мікель

1
Насправді відповідь Нікакіна в основному така.
Мікель

0

Ви можете спробувати замінити небажану частину на sed:

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

а ще краще:

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

1
Потрібно використовувати ^якір для того, щоб замінити лише збіги на початку шляху до каталогу. Крім того, вам не потрібно використовувати, gоскільки команда повинна замінювати максимум 1 зустріч.
Sildoreth

Дякую. Я все ще вчуся цим речам, і ви коментуєте, що це справді корисно.
user1403360

Проблематично, якщо в моєму домашньому каталозі є /home/aliceі у моєму поточному каталозі /home/aliceinchains. Але якщо єдиний раз, коли я хочу використовувати цю функцію, це коли я знаю, що я домашній каталог або один із його підкаталогів, то це має працювати.
Mihai Danila
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.