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.
Tenga en cuenta que si está aplicando esta técnica en otras circunstancias (no PWD, pero alguna otra variable que contenga un nombre de directorio), es posible que deba recortar las barras diagonales finales. A continuación se utiliza el soporte extglob de bash para trabajar incluso con múltiples barras diagonales:
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"
Alternativamente, sin extglob:
dirname="/path/to/somewhere//"
result="${dirname%"${dirname##*[!/]}"}" # extglob-free multi-trailing-/ trim
result="${result##*/}"# remove everything before the last /
¿Cuál es la diferencia entre $ {PWD ## * /} y $ PWD?
Mr_Chimp
24
@Mr_Chimp the first es una operación de expansión de parámetros que recorta el resto del directorio para proporcionar solo el nombre base. Tengo un enlace en mi respuesta a la documentación sobre la expansión de parámetros; siéntase libre de seguir eso si tiene alguna pregunta.
Charles Duffy
24
@stefgosselin $PWDes el nombre de una variable bash incorporada; Todos los nombres de variables incorporados están en mayúsculas (para distinguirlos de las variables locales, que siempre deben tener al menos un carácter en minúscula). result=${PWD#*/}Cómo no valorar a /full/path/to/directory; en su lugar, despoja solo el primer elemento, haciéndolo path/to/directory; El uso de dos #caracteres hace que el patrón coincida con la codicia, haciendo coincidir tantos caracteres como sea posible. Lea la página de expansión de parámetros, vinculada en la respuesta, para más información.
Charles Duffy
55
Tenga en cuenta que el resultado de pwdno siempre es el mismo que el valor de $PWD, debido a las complicaciones que surgen de cdla conexión a través de enlaces simbólicos, si bash tiene la -o physicalopción establecida, etc. Esto solía volverse especialmente desagradable en el manejo de directorios montados automáticamente, donde grabar la ruta física en lugar de la lógica produciría una ruta que, si se usa, permitiría al automontador desmontar espontáneamente el directorio que estaba usando.
Alex North-Keys
3
¡Agradable! Alguien debería escribir un libro para los viejos tipos de conchas de Borne como yo. Tal vez hay uno por ahí? Podría tener un crotchity viejos Administración de Sistemas diciendo cosas como, "en mis tiempos sólo shy cshy si queríamos la tecla de retroceso para trabajar había que leer toda la sttypágina hombre, y nos gustó!"
¿No es este el propósito del basenameprograma? ¿Qué hay de malo en esta respuesta además de faltar las comillas?
Nacht - Restablece a Mónica el
11
@Nacht basenamees de hecho un programa externo que hace lo correcto, pero el funcionamiento de cualquier programa externo para una fiesta que se puede hacer fuera de la caja utilizando solamente funcionalidad integrada es tonto, incurriendo impacto en el rendimiento ( fork(), execve(), wait(), etc.) para Sin razón.
Charles Duffy
3
... como un aparte, mis objeciones basenameaquí no se aplican dirname, porque dirnametiene una funcionalidad que ${PWD##*/}no lo hace, transformando una cadena sin barras ., por ejemplo. Por lo tanto, si bien el uso dirnamecomo herramienta externa tiene una sobrecarga de rendimiento, también tiene una funcionalidad que ayuda a compensarlo.
Charles Duffy
44
@LouisMaddox, un poco de kibitzing: la functionpalabra clave es incompatible con POSIX sin agregar ningún valor sobre la sintaxis estandarizada, y la falta de comillas crearía errores en los nombres de directorio con espacios. wdexec() { "./$(basename "$PWD")"; }podría ser una alternativa preferible.
Charles Duffy
28
Claro que usar basenamees menos "eficiente". Pero probablemente sea más eficiente en términos de productividad del desarrollador porque es fácil de recordar en comparación con la sintaxis de bash feo. Entonces, si lo recuerdas, hazlo. De lo contrario, basenamefunciona igual de bien. ¿Alguien ha tenido que mejorar el "rendimiento" de un script bash y hacerlo más eficiente?
@jocap ... excepto que el uso de echo allí, sin citar el argumento, es incorrecto . Si el nombre del directorio tiene múltiples espacios, o un carácter de tabulación, se contraerá en un solo espacio; Si tiene un carácter comodín, se expandirá. El uso correcto sería echo "${PWD##*/}".
Charles Duffy
99
@jocap ... además, no estoy seguro de que "echo" sea de hecho una parte legítima de la respuesta. La pregunta era cómo obtener la respuesta, no cómo imprimir la respuesta; si el objetivo fuera asignarlo a una variable, por ejemplo, name=${PWD##*/}sería correcto y name=$(echo "${PWD##*/}")sería incorrecto (en un sentido de ineficiencia innecesaria).
Charles Duffy el
24
Puede usar una combinación de pwd y basename. P.ej
Por favor no. Los backticks crean una subshell (por lo tanto, una operación de horquilla), y en este caso, ¡los estás usando dos veces ! [Como una objeción adicional, aunque estilística, los nombres de las variables deben estar en minúsculas a menos que los exporte al entorno o sean un caso especial y reservado].
Charles Duffy, el
11
y, como segundo estilo, los backs de quibble deben ser reemplazados por $ (). todavía se bifurca pero es más legible y se necesita menos excaping.
Jeremy Wall
1
Por convención, las variables de entorno (PATH, EDITOR, SHELL, ...) y las variables internas de shell (BASH_VERSION, RANDOM, ...) están totalmente en mayúsculas. Todos los demás nombres de variables deben estar en minúsculas. Dado que los nombres de las variables distinguen entre mayúsculas y minúsculas, esta convención evita anular accidentalmente las variables ambientales e internas.
Rany Albeg Wein
2
Depende de la convención. Se podría argumentar que todas las variables de shell son variables de entorno (dependiendo del shell) y, por lo tanto, todas las variables de shell deben estar en mayúsculas. Alguien más podría argumentar en función del alcance: las variables globales son mayúsculas, mientras que las variables locales son minúsculas, y todas son globales. Otro podría argumentar que hacer que las variables sean mayúsculas agrega una capa adicional de contraste con los comandos que ensucian los scripts de shell, que también son todas palabras cortas pero significativas en minúsculas. Puedo / no puedo / estoy de acuerdo / con cualquiera de esos argumentos, pero he visto los tres en uso. :)
no lo recomendaría porque parece obtener información sobre el color, mientras pwd | xargs basenameque no ... probablemente no es tan importante, pero la otra respuesta es más simple y más consistente en todos los entornos
davidhq
8
Me gusta la respuesta seleccionada (Charles Duffy), pero tenga cuidado si está en un directorio con enlace simbólico y desea el nombre del directorio de destino. Desafortunadamente, no creo que se pueda hacer en una expresión de expansión de un solo parámetro, tal vez me equivoque. Esto debería funcionar:
Para su información, ${PWD##*/}es POSIX sh: todo moderno / bin / sh (incluido el tablero, ceniza, etc.) lo admite; para llegar a Bourne real en una caja reciente, necesitarías estar en un sistema Solaris ligeramente antiguo. Más allá de eso - echo "$PWD"; omitir las comillas conduce a errores (si el nombre del directorio tiene espacios, caracteres comodín, etc.).
Charles Duffy
1
Sí, estaba usando un viejo sistema Solaris. He actualizado el comando para usar comillas.
sorprendentemente? Sólo bromeando, pero otros son mucho más corto y más fácil de recordar
codewandler
Esto es bastante divertido = P No había oído hablar de $ IFS (separador de campo interno) antes de esto. mi golpe era demasiado viejo, pero puedo probarlo aquí: jdoodle.com/test-bash-shell-script-online
Stan Kurdziel
5
Utilizar:
basename "$PWD"
O
IFS=/
var=($PWD)
echo ${var[-1]}
Convierta el separador de nombre de archivo interno (IFS) de nuevo al espacio.
Necesita más comillas para ser correcto: tal como está, la salida de pwdse divide en cadenas y se expande globalmente antes de pasar a basename.
Charles Duffy
Por lo tanto, basename "$(pwd)"aunque eso es muy ineficiente en comparación con solo basename "$PWD", lo que en sí mismo es ineficiente en comparación con el uso de una expansión de parámetros en lugar de llamar basenameen absoluto.
Esta es, en todos los aspectos, una versión peor de la respuesta dada anteriormente por Arkady ( stackoverflow.com/a/1371267/14122 ): la xargsformulación es ineficaz y tiene errores cuando los nombres de directorio contienen nuevas líneas literales o caracteres de comillas, y la segunda formulación llama al pwdcomando en una subshell, en lugar de recuperar el mismo resultado a través de una expansión variable incorporada.
Charles Duffy
@CharlesDuffy Sin embargo, es una respuesta válida y práctica a la pregunta.
bachph
1
Si desea ver solo el directorio actual en la región de solicitud de bash, puede editar el .bashrcarchivo ~. Cambiar \wa \Wen la línea:
Puede usar la utilidad basename que elimina cualquier prefijo que termine en / y el sufijo (si está presente en una cadena) de la cadena e imprime el resultado en la salida estándar.
Para su información, no viene con mi distribución de Ubuntu.
Katastic Voyage
@KatasticVoyage, está allí en Ubuntu, solo se llama basenameallí. Por lo general, solo se llama gbasenameen MacOS y otras plataformas que de lo contrario se envían con un nombre base no GNU.
Charles Duffy
-1
Los siguientes comandos darán lugar a la impresión de su directorio de trabajo actual en un script bash.
(1) No estoy seguro de dónde estamos asegurando que la lista de argumentos sea tal que $1contendrá el directorio de trabajo actual. (2) El pushdy popdno sirve para nada aquí porque cualquier cosa dentro de los backticks se realiza en una subshell, por lo que no puede afectar el directorio del shell principal para empezar. (3) El uso "$(cd "$1"; pwd)"sería más legible y resistente frente a los nombres de directorio con espacios en blanco.
Respuestas:
No necesita basename, y especialmente no necesita una subshell que ejecute pwd (que agrega una operación de horquilla adicional y costosa ); el shell puede hacer esto internamente usando la expansión de parámetros :
Tenga en cuenta que si está aplicando esta técnica en otras circunstancias (no
PWD
, pero alguna otra variable que contenga un nombre de directorio), es posible que deba recortar las barras diagonales finales. A continuación se utiliza el soporte extglob de bash para trabajar incluso con múltiples barras diagonales:Alternativamente, sin
extglob
:fuente
$PWD
es el nombre de una variable bash incorporada; Todos los nombres de variables incorporados están en mayúsculas (para distinguirlos de las variables locales, que siempre deben tener al menos un carácter en minúscula).result=${PWD#*/}
Cómo no valorar a/full/path/to/directory
; en su lugar, despoja solo el primer elemento, haciéndolopath/to/directory
; El uso de dos#
caracteres hace que el patrón coincida con la codicia, haciendo coincidir tantos caracteres como sea posible. Lea la página de expansión de parámetros, vinculada en la respuesta, para más información.pwd
no siempre es el mismo que el valor de$PWD
, debido a las complicaciones que surgen decd
la conexión a través de enlaces simbólicos, si bash tiene la-o physical
opción establecida, etc. Esto solía volverse especialmente desagradable en el manejo de directorios montados automáticamente, donde grabar la ruta física en lugar de la lógica produciría una ruta que, si se usa, permitiría al automontador desmontar espontáneamente el directorio que estaba usando.sh
ycsh
y si queríamos la tecla de retroceso para trabajar había que leer toda lastty
página hombre, y nos gustó!"Usa el
basename
programa. Para su caso:fuente
basename
programa? ¿Qué hay de malo en esta respuesta además de faltar las comillas?basename
es de hecho un programa externo que hace lo correcto, pero el funcionamiento de cualquier programa externo para una fiesta que se puede hacer fuera de la caja utilizando solamente funcionalidad integrada es tonto, incurriendo impacto en el rendimiento (fork()
,execve()
,wait()
, etc.) para Sin razón.basename
aquí no se aplicandirname
, porquedirname
tiene una funcionalidad que${PWD##*/}
no lo hace, transformando una cadena sin barras.
, por ejemplo. Por lo tanto, si bien el usodirname
como herramienta externa tiene una sobrecarga de rendimiento, también tiene una funcionalidad que ayuda a compensarlo.function
palabra clave es incompatible con POSIX sin agregar ningún valor sobre la sintaxis estandarizada, y la falta de comillas crearía errores en los nombres de directorio con espacios.wdexec() { "./$(basename "$PWD")"; }
podría ser una alternativa preferible.basename
es menos "eficiente". Pero probablemente sea más eficiente en términos de productividad del desarrollador porque es fácil de recordar en comparación con la sintaxis de bash feo. Entonces, si lo recuerdas, hazlo. De lo contrario,basename
funciona igual de bien. ¿Alguien ha tenido que mejorar el "rendimiento" de un script bash y hacerlo más eficiente?
fuente
echo "${PWD##*/}"
.name=${PWD##*/}
sería correcto yname=$(echo "${PWD##*/}")
sería incorrecto (en un sentido de ineficiencia innecesaria).Puede usar una combinación de pwd y basename. P.ej
fuente
¿Qué tal grep:
fuente
pwd | xargs basename
que no ... probablemente no es tan importante, pero la otra respuesta es más simple y más consistente en todos los entornosMe gusta la respuesta seleccionada (Charles Duffy), pero tenga cuidado si está en un directorio con enlace simbólico y desea el nombre del directorio de destino. Desafortunadamente, no creo que se pueda hacer en una expresión de expansión de un solo parámetro, tal vez me equivoque. Esto debería funcionar:
Para ver esto, un experimento:
informa "bar"
DIRNAME
Para mostrar los directorios iniciales de una ruta (sin incurrir en un fork-exec de / usr / bin / dirname):
Esto, por ejemplo, transformará foo / bar / baz -> foo / bar
fuente
readlink -f
es una extensión de GNU y, por lo tanto, no está disponible en los BSD (incluido OS X).Si está utilizando Bourne Shell o
${PWD##*/}
no está disponible.fuente
${PWD##*/}
es POSIX sh: todo moderno / bin / sh (incluido el tablero, ceniza, etc.) lo admite; para llegar a Bourne real en una caja reciente, necesitarías estar en un sistema Solaris ligeramente antiguo. Más allá de eso -echo "$PWD"
; omitir las comillas conduce a errores (si el nombre del directorio tiene espacios, caracteres comodín, etc.).Este hilo es genial! Aquí hay un sabor más:
fuente
Sorprendentemente, nadie mencionó esta alternativa que usa solo comandos bash incorporados:
Como una ventaja adicional , puede obtener fácilmente el nombre del directorio principal con:
Estos funcionarán en Bash 4.3-alpha o más reciente.
fuente
Utilizar:
O
Convierta el separador de nombre de archivo interno (IFS) de nuevo al espacio.
Hay un espacio después del IFS.
fuente
o
fuente
pwd
se divide en cadenas y se expande globalmente antes de pasar abasename
.basename "$(pwd)"
aunque eso es muy ineficiente en comparación con solobasename "$PWD"
, lo que en sí mismo es ineficiente en comparación con el uso de una expansión de parámetros en lugar de llamarbasename
en absoluto.Para los jinetes de búsqueda como yo:
fuente
$PWD
a"$PWD"
para manejar correctamente los nombres de directorio inusuales.generalmente uso esto en scripts sh
puedes usar esto para automatizar cosas ...
fuente
readlink: illegal option -- f usage: readlink [-n] [file ...]
Debajo de grep con regex también funciona,
fuente
Solo usa:
o
fuente
xargs
formulación es ineficaz y tiene errores cuando los nombres de directorio contienen nuevas líneas literales o caracteres de comillas, y la segunda formulación llama alpwd
comando en una subshell, en lugar de recuperar el mismo resultado a través de una expansión variable incorporada.Si desea ver solo el directorio actual en la región de solicitud de bash, puede editar el
.bashrc
archivo~
. Cambiar\w
a\W
en la línea:correr
source ~/.bashrc
y solo mostrará el nombre del directorio en la región de solicitud.Ref: /superuser/60555/show-only-current-directory-name-not-full-path-on-bash-prompt
fuente
Puede usar la utilidad basename que elimina cualquier prefijo que termine en / y el sufijo (si está presente en una cadena) de la cadena e imprime el resultado en la salida estándar.
fuente
Prefiero usar
gbasename
, que es parte de GNU coreutils.fuente
basename
allí. Por lo general, solo se llamagbasename
en MacOS y otras plataformas que de lo contrario se envían con un nombre base no GNU.Los siguientes comandos darán lugar a la impresión de su directorio de trabajo actual en un script bash.
fuente
$1
contendrá el directorio de trabajo actual. (2) Elpushd
ypopd
no sirve para nada aquí porque cualquier cosa dentro de los backticks se realiza en una subshell, por lo que no puede afectar el directorio del shell principal para empezar. (3) El uso"$(cd "$1"; pwd)"
sería más legible y resistente frente a los nombres de directorio con espacios en blanco.