Was ist der einfachste Weg, um einen abschließenden Schrägstrich aus jedem Parameter zu entfernen?

90

Was ist der einfachste Weg, um einen abschließenden Schrägstrich aus jedem Parameter im Array '$ @' zu entfernen, damit rsyncdie Verzeichnisse nach Namen kopiert werden?

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

Der Titel wurde zur Verdeutlichung geändert. Informationen zu den Kommentaren und Antworten zu mehreren nachgestellten Schrägstrichen finden Sie im Bearbeitungsverlauf.

sid_com
quelle
2
Mögliches Duplikat von Slash vom Ende einer Variablen entfernen
Warren Dew

Antworten:

152

Sie können die Verwendung ${parameter%word}Expansion , die detailliert ist hier . Hier ist ein einfaches Testskript, das das Verhalten demonstriert:

#!/bin/bash

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

echo ${@%/}
Sean Bright
quelle
34
+1: Um sehr pedantisch zu sein, wird ein einzelner Schrägstrich entfernt, nicht alle nachgestellten Schrägstriche. So entfernen Sie eine beliebige Anzahl von nachgestellten Schrägstrichen:shopt -s extglob; echo "${@%%+(/)}"
Glenn Jackman
24
Warnung: Möglicherweise möchten Sie nachfolgende Schrägstriche nicht in allen Fällen entfernen. Wenn "/" als Argument angegeben wird, hat das Entfernen des abschließenden Schrägstrichs ... unglückliche Konsequenzen.
Gordon Davisson
13
PROTIP: Kombinieren Sie tr -s /mit variablem regulären Ausdruck , um wiederholte Schrägstriche zu entfernen, und entfernen Sie dann den nachfolgenden Schrägstrich. zBDIR=$(echo //some///badly/written///dir////// | tr -s /); DIR=${DIR%/}
Dave
1
"Ja wirklich?" Laufen set -- one///// two// three four/; shopt -s extglob; echo "${@%%+(/)}"Sie an einer Bash-Eingabeaufforderung und sagen Sie mir, was Sie sehen
Glenn Jackman
1
@twalberg Ich schätze "Protips", die nicht nur alternative Antworten auf die Frage von OP in Kommentarthreads sind.
Kyle Strand
36

Die akzeptierte Antwort schneidet EINEN abschließenden Schrägstrich ab.

Eine Möglichkeit, mehrere nachgestellte Schrägstriche zu kürzen, ist folgende:

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

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

echo $VALUE $TRIMMED

Welche Ausgänge:

/looks/like/a/path/// /looks/like/a/path
Chris Johnson
quelle
1
Vergessen Sie nicht, Ihre Variablen zu zitieren, falls sie Leerzeichen enthalten: TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
Tetsujin
1
Eigentlich ist das im $()Konstrukt nicht nötig . Es ist jedoch auch harmlos :) Daher ist es wahrscheinlich eine gute Praxis, doppelte Anführungszeichen zu verwenden, "$VALUE"damit Sie nicht entscheiden müssen, wann und wann Sie die doppelten Anführungszeichen nicht verwenden möchten.
Chris Johnson
Gibt es eine Möglichkeit, dies mit einer früheren Erfassung zu kombinieren? Ich möchte das Protokoll und (falls vorhanden) den abschließenden Schrägstrich von einer URL entfernen, echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)/*$|\1|'funktioniert aber nicht (da die Erfassungsgruppe auch mit dem abschließenden Schrägstrich übereinstimmt, denke ich). Ich kann es mit zwei Befehlen machen: echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)$|\1|' -e 's|/*$||'aber ich habe mich gefragt, ob es mit einem gemacht werden kann?
Adam
Diese Antwort funktionierte bei mir mit einer sehr großen Eingabedatei besser. Ein einfacher sed 's:/*$::' < in.txt > out.txterledigt den Job in Sekunden
MitchellK
19

Das funktioniert bei mir: ${VAR%%+(/)}

Wie hier beschrieben http://wiki.bash-hackers.org/syntax/pattern

Möglicherweise muss die Shell-Option extglob festgelegt werden. Ich kann nicht sehen, dass es für mich aktiviert ist, aber es funktioniert immer noch

Ivan
quelle
2
So shopt extglob
fragen Sie
Dies ist Extended Pattern Language und Sie müssen festlegen extglob.
Ingyhere
1
Dies funktioniert nicht unter Mac OS Xs integriertem Bash. Die Lösung von Sean Bright oben lautet:${VAR%/}
Alec Jacobson
11

realpathlöst den angegebenen Pfad auf. Unter anderem werden auch nachgestellte Schrägstriche entfernt. Verwenden Sie -sdiese Option, um folgende Simlinks zu vermeiden

DIR=/tmp/a///
echo $(realpath -s $DIR)
# output: /tmp/a
czerny
quelle
1
Es erfordert alle Knoten im Pfad mit Ausnahme des letzten. Wenn der Benutzer einen nicht existierenden Pfad eingibt, schlägt dies realpathfehl.
Livy
1
@Livy realpath --canonicalize-missingfunktioniert absolut korrekt mit jedem nicht vorhandenen Teil des Pfades
maoizm
7

Zu Ihrer Information, ich habe diese beiden Funktionen .bash_profilebasierend auf den Antworten auf SO zu meinen hinzugefügt . Wie Chris Johnson sagte, ${x%/}entfernen alle Antworten, bei denen nur ein Schrägstrich verwendet wird, das, was sie sagen, und hoffen, dass dies nützlich ist.

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

force_trailing_slash() {
    echo "$(rem_trailing_slash "$1")/"
}
Jonathan H.
quelle
4

In zsh können Sie den :aModifikator verwenden.

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

echo "${DIRECTORY:a}"

=> /some/path/name

Dies realpathverhält sich wie , fehlt jedoch nicht mit fehlenden Dateien / Verzeichnissen als Argument.

Nicolai Fröhlich
quelle