¿Cuál es la forma más sencilla de eliminar una barra al final de cada parámetro?


98

¿Cuál es la forma más sencilla de eliminar una barra al final de cada parámetro en la matriz '$ @', de modo que rsynccopie los directorios por nombre?

rsync -a --exclude='*~' "$@" "$dir"

Se ha cambiado el título para aclararlo. Para comprender los comentarios y responder sobre múltiples barras inclinadas, consulte el historial de ediciones.


Respuestas:


160

Puede utilizar la ${parameter%word}expansión que se detalla aquí . Aquí hay un script de prueba simple que demuestra el comportamiento:

#!/bin/bash

# Call this as:
#   ./test.sh one/ two/ three/ 
#
# Output:
#  one two three

echo ${@%/}

35
+1: Para ser muy pedante, eso eliminará una sola barra, no todas las barras finales. Para eliminar cualquier número de barras al final:shopt -s extglob; echo "${@%%+(/)}"
Glenn Jackman

24
Advertencia: es posible que no desee eliminar las barras inclinadas en todos los casos. Si se proporciona "/" como argumento, eliminar la barra inclinada tendrá ... consecuencias desafortunadas.
Gordon Davisson

13
PROTIP: Combine tr -s /con expresión regular variable para eliminar las barras repetidas y luego elimine la barra final. pDIR=$(echo //some///badly/written///dir////// | tr -s /); DIR=${DIR%/}
Dave

1
De Verdad? En una fiesta de aviso, ejecución set -- one///// two// three four/; shopt -s extglob; echo "${@%%+(/)}"y dime lo que ves
Glenn Jackman

1
@twalberg Aprecio los "protips" que no son solo respuestas alternativas a la pregunta de OP en los hilos de comentarios.
Kyle Strand

39

La respuesta aceptada recortará UNA barra al final.

Una forma de recortar varias barras al final es la siguiente:

VALUE=/looks/like/a/path///

TRIMMED=$(echo $VALUE | sed 's:/*$::')

echo $VALUE $TRIMMED

Qué salidas:

/looks/like/a/path/// /looks/like/a/path

1
No olvide citar sus variables, en caso de que contengan espacios en blanco: TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
tetsujin

1
En realidad, eso no es necesario dentro de la $()construcción. Sin embargo, también es inofensivo :) por lo que probablemente sea una buena práctica usar comillas dobles como "$VALUE"para no tener que decidir cuándo y cuándo no usar las comillas dobles.
Chris Johnson

¿Alguna forma de combinar esto con una captura anterior? Quiero eliminar el protocolo y (si está presente) la barra diagonal de una URL, pero echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)/*$|\1|'no funciona (ya que el grupo de captura también coincide con la barra final, supongo). Puedo hacerlo con dos comandos: echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)$|\1|' -e 's|/*$||'pero me preguntaba si se podría hacer con uno.
Adam

Esta respuesta funcionó mejor para mí con un archivo de entrada muy grande. Un simple sed 's:/*$::' < in.txt > out.txthace el trabajo en segundos
MitchellK

22

Esto funciona para mi: ${VAR%%+(/)}

Como se describe aquí http://wiki.bash-hackers.org/syntax/pattern

Es posible que deba configurar la opción de shell extglob. No puedo verlo habilitado para mí, pero aún funciona


2
Para consultar una configuración: shopt extglobsin opciones
glenn jackman

Este es el lenguaje de patrones extendido y debe configurarlo extglob.
ingyhere

1
Esto no funciona en el bash integrado de Mac OS X. La solución de Sean Bright anterior lo hace:${VAR%/}
Alec Jacobson

13

realpathresuelve el camino dado. Entre otras cosas, también elimina las barras inclinadas. Úselo -spara evitar los siguientes enlaces SIM

DIR=/tmp/a///
echo $(realpath -s $DIR)
# output: /tmp/a

1
Requiere que todos los nodos de la ruta existan excepto el último. Si el usuario arroja algún camino de inexistencia, realpathfallará.
Livy

2
@Livy realpath --canonicalize-missingfunciona absolutamente correctamente con cualquier parte no existente de la ruta
maoizm

y falta realpath en algunas plataformas :-(
Mark Ribau

8

Para su información, agregué estas dos funciones a mi .bash_profilebasado en las respuestas encontradas en SO. Como dijo Chris Johnson, todas las respuestas que usan ${x%/}eliminan solo una barra, estas funciones harán lo que dicen, espero que esto sea útil.

rem_trailing_slash() {
    echo "$1" | sed 's/\/*$//g'
}

force_trailing_slash() {
    echo "$(rem_trailing_slash "$1")/"
}

4

En zsh puedes usar el :amodificador.

export DIRECTORY='/some//path/name//'

echo "${DIRECTORY:a}"

=> /some/path/name

Esto actúa como realpathpero no falla con archivos / directorios faltantes como argumento.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.