result=${PWD##*/} # to assign to a variable
printf '%s\n' "${PWD##*/}" # to print to stdout
# ...more robust than echo for unusual names
# (consider a directory named -e or -n)
printf '%q\n' "${PWD##*/}" # to print to stdout, quoted for use as shell input
# ...useful to make hidden characters readable.
Observe que, se você estiver aplicando essa técnica em outras circunstâncias (não PWD, mas em alguma outra variável com um nome de diretório), poderá ser necessário aparar as barras finais. A seguir, use o suporte extglob do bash para funcionar mesmo com várias barras finais:
dirname=/path/to/somewhere//
shopt -s extglob # enable +(...) glob syntax
result=${dirname%%+(/)}# trim however many trailing slashes exist
result=${result##*/} # remove everything before the last / that still remains
printf '%s\n'"$result"
Como alternativa, sem extglob:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}"# remove everything before the last /
O @Mr_Chimp the first é uma operação de expansão de parâmetro que apara o restante do diretório para fornecer apenas o nome da base. Eu tenho um link na minha resposta para a documentação sobre expansão de parâmetros; sinta-se à vontade para acompanhar isso se tiver alguma dúvida.
Charles Duffy
24
@stefgosselin $PWDé o nome de uma variável bash interna ; todos os nomes de variáveis integrados estão em maiúsculas (para diferenciá-los das variáveis locais, que sempre devem ter pelo menos um caractere minúsculo). result=${PWD#*/}faz não avaliar a /full/path/to/directory; em vez disso, retira apenas o primeiro elemento, tornando-o path/to/directory; o uso de dois #caracteres faz com que o padrão seja ganancioso, correspondendo ao máximo de caracteres possível. Leia a página de expansão de parâmetros, vinculada na resposta, para mais informações.
precisa
5
Observe que a saída de pwdnem sempre é igual ao valor de $PWD, devido a complicações decorrentes de cdlinks simbólicos, se o bash tem a -o physicalopção definida e assim por diante. Isso costumava ficar especialmente desagradável ao lidar com diretórios montados automaticamente, onde a gravação do caminho físico em vez do lógico produziria um caminho que, se usado, permitiria ao montador desmontar espontaneamente o diretório que estava usando.
Alex North-Keys
3
Agradável! Alguém deveria escrever um livro para velhos caras do Borne como eu. Talvez haja um por aí? Poderia ter um crotchity sys velhos admin dizendo coisas como, "de volta no meu dia apenas she cshe se você queria a tecla de retrocesso para o trabalho que você tinha que ler toda sttypágina do homem, e nós gostamos!"
Não é esse o objetivo do basenameprograma? O que há de errado com essa resposta, além de perder as aspas?
Nacht - Restabelece Monica
11
@Nacht basenameé de fato um programa externo que faz a coisa certa, mas a execução de qualquer programa externo para uma festança coisa pode fazer out-of-the-box usando apenas funcionalidade interna é bobagem, incorrendo impacto no desempenho ( fork(), execve(), wait(), etc) para sem motivo.
Charles Duffy
3
... como um aparte, minhas objeções basenameaqui não se aplicam dirname, porque dirnametem uma funcionalidade que ${PWD##*/}não - transformar uma string sem barras para ., por exemplo. Portanto, embora o uso dirnamecomo ferramenta externa tenha sobrecarga de desempenho, também possui funcionalidade que ajuda a compensar a mesma.
Charles Duffy
4
@LouisMaddox, um pouco desconcertante: a functionpalavra-chave é incompatível com POSIX sem adicionar nenhum valor à sintaxe padronizada, e a falta de aspas criaria erros nos nomes de diretórios com espaços. wdexec() { "./$(basename "$PWD")"; }pode ser uma alternativa preferível.
Charles Duffy
28
Claro que usar basenameé menos "eficiente". Mas é provavelmente mais eficiente em termos de produtividade do desenvolvedor, porque é fácil de lembrar em comparação com a feia sintaxe do bash. Então, se você se lembra, vá em frente. Caso contrário, basenamefunciona tão bem. Alguém já teve que melhorar o "desempenho" de um script bash e torná-lo mais eficiente?
@jocap ... exceto que o uso de eco lá, sem citar o argumento, está errado . Se o nome do diretório tiver vários espaços ou um caractere de tabulação, ele será recolhido em um único espaço; se tiver um caractere curinga, será expandido. O uso correto seria echo "${PWD##*/}".
Charles Duffy
9
@jocap ... também, não tenho certeza de que "eco" seja de fato uma parte legítima da resposta. A questão era como obter a resposta, não como imprimir a resposta; se o objetivo era atribuí-lo a uma variável, por exemplo, name=${PWD##*/}estaria certo e name=$(echo "${PWD##*/}")errado (no sentido de ineficiência desnecessária).
Charles Duffy
24
Você pode usar uma combinação de pwd e basename. Por exemplo
Por favor não. Os backticks criam um subshell (portanto, uma operação de fork) - e, neste caso, você os está usando duas vezes ! [Como uma queixa adicional, ainda que estilística - os nomes das variáveis devem estar em letras minúsculas, a menos que você os exporte para o ambiente ou se for um caso reservado especial].
Charles Duffy
11
e, como segundo estilo, os backtics de quibble devem ser substituídos por $ (). garfos ainda mais legíveis e com menos excaping necessário.
Jeremy Wall
1
Por convenção, as variáveis de ambiente (PATH, EDITOR, SHELL, ...) e variáveis internas do shell (BASH_VERSION, RANDOM, ...) são totalmente capitalizadas. Todos os outros nomes de variáveis devem estar em minúsculas. Como os nomes das variáveis diferenciam maiúsculas de minúsculas, essa convenção evita a substituição acidental de variáveis ambientais e internas.
Rany Albeg Wein
2
Depende da convenção. Pode-se argumentar que todas as variáveis do shell são variáveis de ambiente (dependendo do shell) e, portanto, todas as variáveis do shell devem estar em maiúsculas. Alguém poderia argumentar com base no escopo - variáveis globais são maiúsculas, enquanto variáveis locais são minúsculas e todas são globais. Ainda outro pode argumentar que a criação de variáveis em maiúsculas adiciona uma camada extra de contraste com os comandos que cobrem os scripts do shell, que também são palavras curtas, mas significativas, em minúsculas. Posso ou não concordar / com qualquer um desses argumentos, mas vi os três em uso. :)
não recomendaria porque parece para obter alguma informação de cor enquanto pwd | xargs basenamenão .. provavelmente não tão importante, mas a outra resposta é mais simples e mais consistente em ambientes
davidhq
8
Gosto da resposta selecionada (Charles Duffy), mas tenha cuidado se você estiver em um diretório com link simbólico e quiser o nome do diretório de destino. Infelizmente, não acho que isso possa ser feito em uma expressão de expansão de parâmetro único, talvez eu esteja enganado. Isso deve funcionar:
Para sua informação, ${PWD##*/}é o POSIX sh - todo moderno / bin / sh (incluindo dash, ash, etc) suporta; para atingir o Bourne real em uma caixa recente, você precisa estar em um sistema Solaris levemente antigo. Além disso - echo "$PWD"; deixar de fora as aspas leva a erros (se o nome do diretório tiver espaços, caracteres curinga, etc.).
Charles Duffy
1
Sim, eu estava usando um sistema Solaris antigo. Eu atualizei o comando para usar aspas.
surpreendentemente? apenas brincando, mas outras são muito mais curto e fácil de lembrar
codewandler
Isso é bem engraçado = P Não tinha ouvido falar em $ IFS (separador interno de campos) antes disso. minha festa era muito velho, mas pode testá-lo aqui: jdoodle.com/test-bash-shell-script-online
Stan Kurdziel
5
Usar:
basename "$PWD"
OU
IFS=/
var=($PWD)
echo ${var[-1]}
Volte o IFS (Internal Filename Separator) de volta ao espaço.
Precisa de mais aspas para estar correto - como é, a saída de pwdé dividida em cadeia e expandida antes de ser passada para basename.
Charles Duffy
Assim, basename "$(pwd)"- apesar de que é muito ineficiente em comparação com apenas basename "$PWD", que é em si ineficiente em comparação ao uso de uma expansão de parâmetros em vez de chamar basenamea todos.
Essa é, em todos os aspectos, uma versão pior da resposta fornecida anteriormente por Arkady ( stackoverflow.com/a/1371267/14122 ): A xargsformulação é ineficiente e com erros quando os nomes de diretório contêm linhas de nova linha literais ou caracteres de aspas, e a segunda formulação chama o pwdcomando em uma subshell, em vez de recuperar o mesmo resultado por meio de uma expansão variável interna.
Charles Duffy
@CharlesDuffy Não obstante, é uma resposta válida e prática à pergunta.
bachph 14/03
1
Se você quiser ver apenas o diretório atual na região do prompt do bash, poderá editar o .bashrcarquivo ~. Mude \wpara \Wna linha:
Você pode usar o utilitário basename, que exclui qualquer prefixo que termine em / e o sufixo (se presente na string) da string e imprime o resultado na saída padrão.
Para sua informação, ele não vem com minha distribuição do Ubuntu.
Katastic Voyage
@ KatasticVoyage, está lá no Ubuntu, é chamado apenas basenamelá. Normalmente, ele é chamado apenas gbasenameno MacOS e em outras plataformas que são fornecidas com um nome de base não-GNU.
Charles Duffy
-1
Os comandos a seguir resultarão na impressão do diretório de trabalho atual em um script bash.
(1) Não sei ao certo onde estamos garantindo que a lista de argumentos seja tal que $1contenha o diretório de trabalho atual. (2) O pushde popdnão serve para nada aqui, porque qualquer coisa dentro dos backticks é feita em um subshell - portanto, não pode afetar o diretório do shell pai para começar. (3) O uso "$(cd "$1"; pwd)"seria mais legível e flexível em relação aos nomes de diretório com espaço em branco.
Respostas:
Não há necessidade de nome de base e, especialmente, não é necessário um subshell executando o pwd (que adiciona uma operação de garfo extra e cara ); o shell pode fazer isso internamente usando a expansão de parâmetros :
Observe que, se você estiver aplicando essa técnica em outras circunstâncias (não
PWD
, mas em alguma outra variável com um nome de diretório), poderá ser necessário aparar as barras finais. A seguir, use o suporte extglob do bash para funcionar mesmo com várias barras finais:Como alternativa, sem
extglob
:fonte
$PWD
é o nome de uma variável bash interna ; todos os nomes de variáveis integrados estão em maiúsculas (para diferenciá-los das variáveis locais, que sempre devem ter pelo menos um caractere minúsculo).result=${PWD#*/}
faz não avaliar a/full/path/to/directory
; em vez disso, retira apenas o primeiro elemento, tornando-opath/to/directory
; o uso de dois#
caracteres faz com que o padrão seja ganancioso, correspondendo ao máximo de caracteres possível. Leia a página de expansão de parâmetros, vinculada na resposta, para mais informações.pwd
nem sempre é igual ao valor de$PWD
, devido a complicações decorrentes decd
links simbólicos, se o bash tem a-o physical
opção definida e assim por diante. Isso costumava ficar especialmente desagradável ao lidar com diretórios montados automaticamente, onde a gravação do caminho físico em vez do lógico produziria um caminho que, se usado, permitiria ao montador desmontar espontaneamente o diretório que estava usando.sh
ecsh
e se você queria a tecla de retrocesso para o trabalho que você tinha que ler todastty
página do homem, e nós gostamos!"Use o
basename
programa. Para o seu caso:fonte
basename
programa? O que há de errado com essa resposta, além de perder as aspas?basename
é de fato um programa externo que faz a coisa certa, mas a execução de qualquer programa externo para uma festança coisa pode fazer out-of-the-box usando apenas funcionalidade interna é bobagem, incorrendo impacto no desempenho (fork()
,execve()
,wait()
, etc) para sem motivo.basename
aqui não se aplicamdirname
, porquedirname
tem uma funcionalidade que${PWD##*/}
não - transformar uma string sem barras para.
, por exemplo. Portanto, embora o usodirname
como ferramenta externa tenha sobrecarga de desempenho, também possui funcionalidade que ajuda a compensar a mesma.function
palavra-chave é incompatível com POSIX sem adicionar nenhum valor à sintaxe padronizada, e a falta de aspas criaria erros nos nomes de diretórios com espaços.wdexec() { "./$(basename "$PWD")"; }
pode ser uma alternativa preferível.basename
é menos "eficiente". Mas é provavelmente mais eficiente em termos de produtividade do desenvolvedor, porque é fácil de lembrar em comparação com a feia sintaxe do bash. Então, se você se lembra, vá em frente. Caso contrário,basename
funciona tão bem. Alguém já teve que melhorar o "desempenho" de um script bash e torná-lo mais eficiente?O que outras pessoas estão dizendo
fonte
echo "${PWD##*/}"
.name=${PWD##*/}
estaria certo ename=$(echo "${PWD##*/}")
errado (no sentido de ineficiência desnecessária).Você pode usar uma combinação de pwd e basename. Por exemplo
fonte
Que tal grep:
fonte
pwd | xargs basename
não .. provavelmente não tão importante, mas a outra resposta é mais simples e mais consistente em ambientesGosto da resposta selecionada (Charles Duffy), mas tenha cuidado se você estiver em um diretório com link simbólico e quiser o nome do diretório de destino. Infelizmente, não acho que isso possa ser feito em uma expressão de expansão de parâmetro único, talvez eu esteja enganado. Isso deve funcionar:
Para ver isso, um experimento:
relatórios "barra"
DIRNAME
Para mostrar os principais diretórios de um caminho (sem incorrer em um fork-exec de / usr / bin / dirname):
Isto irá, por exemplo, transformar foo / bar / baz -> foo / bar
fonte
readlink -f
é uma extensão GNU e, portanto, não está disponível nos BSDs (incluindo o OS X).Se você estiver usando o Bourne shell ou
${PWD##*/}
não estiver disponível.fonte
${PWD##*/}
é o POSIX sh - todo moderno / bin / sh (incluindo dash, ash, etc) suporta; para atingir o Bourne real em uma caixa recente, você precisa estar em um sistema Solaris levemente antigo. Além disso -echo "$PWD"
; deixar de fora as aspas leva a erros (se o nome do diretório tiver espaços, caracteres curinga, etc.).Esta discussão é ótima! Aqui está mais um sabor:
fonte
Surpreendentemente, ninguém mencionou essa alternativa que usa apenas comandos bash internos:
Como um bônus adicional, você pode facilmente obter o nome do diretório pai com:
Eles funcionarão no Bash 4.3-alpha ou mais recente.
fonte
Usar:
OU
Volte o IFS (Internal Filename Separator) de volta ao espaço.
Há um espaço após o IFS.
fonte
ou
fonte
pwd
é dividida em cadeia e expandida antes de ser passada parabasename
.basename "$(pwd)"
- apesar de que é muito ineficiente em comparação com apenasbasename "$PWD"
, que é em si ineficiente em comparação ao uso de uma expansão de parâmetros em vez de chamarbasename
a todos.Para os jóqueis por aí como eu:
fonte
$PWD
para"$PWD"
para manipular corretamente nomes de diretório incomuns.Eu costumo usar isso em scripts sh
você pode usar isso para automatizar as coisas ...
fonte
readlink: illegal option -- f usage: readlink [-n] [file ...]
Abaixo grep com regex também está funcionando,
fonte
Apenas use:
ou
fonte
xargs
formulação é ineficiente e com erros quando os nomes de diretório contêm linhas de nova linha literais ou caracteres de aspas, e a segunda formulação chama opwd
comando em uma subshell, em vez de recuperar o mesmo resultado por meio de uma expansão variável interna.Se você quiser ver apenas o diretório atual na região do prompt do bash, poderá editar o
.bashrc
arquivo~
. Mude\w
para\W
na linha:Execute
source ~/.bashrc
e ele exibirá apenas o nome do diretório na região do prompt.Ref: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
fonte
Você pode usar o utilitário basename, que exclui qualquer prefixo que termine em / e o sufixo (se presente na string) da string e imprime o resultado na saída padrão.
fonte
Eu prefiro usar
gbasename
, que faz parte do GNU coreutils.fonte
basename
lá. Normalmente, ele é chamado apenasgbasename
no MacOS e em outras plataformas que são fornecidas com um nome de base não-GNU.Os comandos a seguir resultarão na impressão do diretório de trabalho atual em um script bash.
fonte
$1
contenha o diretório de trabalho atual. (2) Opushd
epopd
não serve para nada aqui, porque qualquer coisa dentro dos backticks é feita em um subshell - portanto, não pode afetar o diretório do shell pai para começar. (3) O uso"$(cd "$1"; pwd)"
seria mais legível e flexível em relação aos nomes de diretório com espaço em branco.