Qual è il modo più semplice per rimuovere una barra finale da ogni parametro?


98

Qual è il modo più semplice per rimuovere una barra finale da ogni parametro nell'array "$ @", in modo che rsyncle directory vengano copiate per nome?

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

Il titolo è stato cambiato per chiarimenti. Per comprendere i commenti e le risposte su più barre finali, vedere la cronologia delle modifiche.


Risposte:


160

È possibile utilizzare l' ${parameter%word}espansione descritta in dettaglio qui . Ecco un semplice script di test che dimostra il comportamento:

#!/bin/bash

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

echo ${@%/}

35
+1: Per essere molto pedante, rimuoverai un singolo taglio, non tutti i tagli finali. Per rimuovere un numero qualsiasi di barre finali:shopt -s extglob; echo "${@%%+(/)}"
glenn jackman

24
Attenzione: potresti non voler rimuovere le barre finali in tutti i casi. Se "/" viene fornito come argomento, la rimozione della barra finale avrà ... conseguenze sfortunate.
Gordon Davisson

13
PROTIP: Combina tr -s /con regex variabile per rimuovere le barre ripetute, quindi rimuovere la barra finale. ad esempioDIR=$(echo //some///badly/written///dir////// | tr -s /); DIR=${DIR%/}
Dave

1
Veramente? Ad un prompt di bash, corri set -- one///// two// three four/; shopt -s extglob; echo "${@%%+(/)}"e dimmi cosa vedi
glenn jackman

1
@twalberg Apprezzo i "protips" che non sono solo risposte alternative alla domanda di OP nei thread dei commenti.
Kyle Strand

39

La risposta accettata taglierà UNA barra finale.

Un modo per tagliare più barre finali è questo:

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

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

echo $VALUE $TRIMMED

Quali uscite:

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

1
Non dimenticare di citare le tue variabili, nel caso contengano spazi: TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
tetsujin

1
In realtà questo non è necessario all'interno del $()costrutto. Tuttavia è anche innocuo :) quindi probabilmente è una buona pratica usare le virgolette doppie in "$VALUE"modo da non dover decidere quando e quando non usare le virgolette doppie.
Chris Johnson

Qualche modo per combinare questo con un'acquisizione precedente? Voglio rimuovere il protocollo e (se presente) la barra finale da un URL ma echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)/*$|\1|'non funziona (poiché il gruppo di cattura corrisponde anche alla barra finale, immagino). Posso farlo con due comandi: echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)$|\1|' -e 's|/*$||'ma ti chiedevi se si potesse fare con uno?
Adam

Questa risposta ha funzionato meglio per me con un file di input molto grande. Un semplice sed 's:/*$::' < in.txt > out.txtfa il lavoro in pochi secondi
MitchellK

22

Questo funziona per me: ${VAR%%+(/)}

Come descritto qui http://wiki.bash-hackers.org/syntax/pattern

Potrebbe essere necessario impostare l'opzione di shell extglob. Non riesco a vederlo abilitato per me ma funziona ancora


2
Per interrogare un'impostazione: shopt extglobsenza opzioni
glenn jackman

Questo è Extended Pattern Language e devi impostarlo extglob.
ingyhere

1
Questo non funziona sulla bash incorporata di Mac OS X. La soluzione di Sean Bright sopra fa:${VAR%/}
Alec Jacobson

13

realpathrisolve un dato percorso. Tra le altre cose rimuove anche le barre finali. Da usare -sper evitare di seguire i collegamenti simulati

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

1
Richiede l'esistenza di tutti i nodi nel percorso tranne l'ultimo. Se l'utente inserisce un percorso inesistente, realpathfallirà.
Livio

2
@Livy realpath --canonicalize-missingfunziona in modo assolutamente corretto con qualsiasi parte inesistente del percorso
maoizm

e realpath manca su alcune piattaforme :-(
Mark Ribau

8

Cordiali saluti, ho aggiunto queste due funzioni al mio in .bash_profilebase alle risposte trovate su SO. Come ha detto Chris Johnson, tutte le risposte che utilizzano ${x%/}rimuovono solo una barra, queste funzioni faranno quello che dicono, spero che questo sia utile.

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

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

4

In zsh puoi usare il :amodificatore.

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

echo "${DIRECTORY:a}"

=> /some/path/name

Funziona come realpathma non fallisce con file / directory mancanti come argomento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.