Faça o resultado pwd em termos de "~"?

28

pwd me dá

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

Existe uma maneira fácil de obter

~/some/random/folder

de pwd?

Sibbs Gambling
fonte
A tubulação através do sed é uma opção?
Matthew D. Scholefield
7
Se você estiver indo para fazer isso, eu fortemente recomendo nomeando o comando algo resultando diferente pwd. Caso contrário, você interromperá os scripts que esperam usar sua saída em contextos que não realizam expansão de til.
Charles Duffy

Respostas:

25

Se você estiver usando o bash, o dirsbuilt-in terá o comportamento desejado:

dirs +0
~/some/random/folder

(Note +0, not -0.)

Com zsh:

dirs
~/some/random/folder

Para ser exato, primeiro precisamos limpar a pilha de diretórios, caso contrário dirs, imprimiríamos todo o conteúdo:

dirs -c; dirs

Ou com zsho printbuiltin:

print -rD $PWD

ou

print -P %~

(que ativa a expansão rápida . %~in se $PS1expande para o diretório atual com $HOMEsubstituído, ~mas também lida com outros diretórios nomeados, como o diretório inicial de outros usuários ou diretórios nomeados que você define por si mesmo).

caos
fonte
Eu alterno o tempo todo entre bash e zsh. Infelizmente, esta solução me obriga a lembrar a diferença entre as conchas e também a lembrar (verificar) onde estou atualmente. A resposta de @Bichoy é agnóstica para esses dois.
avp
18

Você pode usar o recurso de substituição de substring variável do Bash:

$ pwd
/home/vagrant/foo/bar
$ echo ${PWD/#$HOME/'~'}
~/foo/bar
Nykakin
fonte
2
Isso também funciona em kshe zsh.
precisa saber é o seguinte
1
Embora eu tenha votado positivamente nesta resposta porque é a maneira mais fácil, há uma pequena advertência aqui: dentro de / tmp / home / nome de usuário, isso retornará / tmp ~. Não consigo encontrar uma maneira de inserir um sinal de sinal de intercalação antes de $ HOME para corrigir isso. Se você precisar de sua solução para ser perfeito, não use isso ...
0fnt
1
@ user18151, do que você por apontar isso. Substituí minha resposta à ${string/#substring/replacement}versão para evitar esse comportamento.
Nykakin
1
@ mr.spuratic está correto (exceto pelo uso de echo) em zsh. Em outras conchas, $HOMEseria tratado como um padrão e a coisa toda sujeita a divisão + glob.
Stéphane Chazelas
Escapar do til ('~') fez o truque. Observe que \ ~ também funciona. Isso é conveniente quando já está no contexto ': eg,PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Atafar
7

Usando sed:

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

A idéia é usar qualquer caractere com menor probabilidade de aparecer em um caminho de diretório inicial como o delimitador no sedregex. No exemplo acima, estou usando |.

O lado bom dessa técnica é que ela é realmente independente de shell.

Você também pode usar o alias pwdpara /bin/pwd | sed "s|$HOME|~|"obter esse comportamento em outros scripts que possam estar usando pwd.

Bichoy
fonte
2
Você precisa incluir a ^âncora no seu regex. Caso contrário, é possível (por mais improvável) que isso substitua um segmento no meio do caminho.
precisa saber é o seguinte
Na verdade, a regex deve ter a seguinte aparência "s|^/home/user\(/.*\)\?$|~\1|". Caso contrário, ele corresponde caminhos de outros usuários se os seus nomes são como user1, user2, user3e você corresponder apenasuser
avp
3
tilde=\~${PWD#~}

Eu acho que é isso que você quer?

O que é interessante sobre o til é quando ele é expandido como um padrão que não precisa ser citado. Usar $HOMEda mesma maneira sem aspas renderia resultados imprevisíveis porque qualquer um de seus caracteres constituintes poderia ser caracteres padrão e, portanto, nem sempre renderia o resultado esperado.

Mas a expansão til deve sempre ocorrer como se fosse o resultado de uma expansão citada e, portanto, seus resultados são previsíveis. Isso parece verdadeiro em praticamente todos os shell que testei para casepadrões e parâmetros, com as notáveis ​​exceções de ambos ksh93e mkshpor qualquer motivo - nenhum dos quais parece honrar o aspecto citado do til nessa capacidade.

Outra coisa interessante sobre isso é que você pode redefinir $HOMEpara manipular qualquer diretório da mesma maneira. Por exemplo:

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

Aqui está outro exemplo:

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
fonte
1
Essa é uma abordagem realmente interessante. Mas assume que $PWDestá abaixo $HOME. Você pode usar a mesma idéia combinada com a substituição de padrões para torná-la mais geral. Como é ${PWD/#~/\~}?
Mikel
1
Na verdade, a resposta de Nykakin é basicamente isso.
Mikel
0

Você pode tentar substituir a parte indesejada por sed:

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

ou melhor ainda:

pwd | sed "s,^$HOME,~,"
user1403360
fonte
1
Você precisa usar a ^âncora para garantir que apenas correspondências no início do caminho do diretório sejam substituídas. Além disso, você não precisa usá-lo gporque o comando deve substituir 1 ocorrência no máximo.
precisa saber é o seguinte
Obrigado. Eu ainda estou aprendendo essas coisas e você comenta é realmente útil.
precisa saber é o seguinte
Problema se meu diretório pessoal for /home/alicee meu diretório atual for /home/aliceinchains. Mas se a única vez em que eu quiser usar o recurso for quando eu souber que sou meu diretório pessoal ou um de seus subdiretórios, ele deverá funcionar.
22717 Mihai Danila