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:
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).
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:
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.
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
~
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:
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.
pwd
. Caso contrário, você interromperá os scripts que esperam usar sua saída em contextos que não realizam expansão de til.Respostas:
Se você estiver usando o bash, o
dirs
built-in terá o comportamento desejado:(Note
+0
, not-0
.)Com
zsh
:Para ser exato, primeiro precisamos limpar a pilha de diretórios, caso contrário
dirs
, imprimiríamos todo o conteúdo:Ou com
zsh
oprint
builtin:ou
(que ativa a expansão rápida .
%~
in se$PS1
expande para o diretório atual com$HOME
substituí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).fonte
Você pode usar o recurso de substituição de substring variável do Bash:
fonte
ksh
ezsh
.${string/#substring/replacement}
versão para evitar esse comportamento.echo
) emzsh
. Em outras conchas,$HOME
seria tratado como um padrão e a coisa toda sujeita a divisão + glob.PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}"'
Usando
sed
:A idéia é usar qualquer caractere com menor probabilidade de aparecer em um caminho de diretório inicial como o delimitador no
sed
regex. No exemplo acima, estou usando|
.O lado bom dessa técnica é que ela é realmente independente de shell.
Você também pode usar o alias
pwd
para/bin/pwd | sed "s|$HOME|~|"
obter esse comportamento em outros scripts que possam estar usandopwd
.fonte
^
âncora no seu regex. Caso contrário, é possível (por mais improvável) que isso substitua um segmento no meio do caminho."s|^/home/user\(/.*\)\?$|~\1|"
. Caso contrário, ele corresponde caminhos de outros usuários se os seus nomes são comouser1
,user2
,user3
e você corresponder apenasuser
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
$HOME
da 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
case
padrões e parâmetros, com as notáveis exceções de ambosksh93
emksh
por qualquer motivo - nenhum dos quais parece honrar o aspecto citado do til nessa capacidade.Outra coisa interessante sobre isso é que você pode redefinir
$HOME
para manipular qualquer diretório da mesma maneira. Por exemplo:Aqui está outro exemplo:
fonte
$PWD
está abaixo$HOME
. Você pode usar a mesma idéia combinada com a substituição de padrões para torná-la mais geral. Como é${PWD/#~/\~}
?Você pode tentar substituir a parte indesejada por
sed
:ou melhor ainda:
fonte
^
â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á-log
porque o comando deve substituir 1 ocorrência no máximo./home/alice
e 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.