Jaki jest najprostszy sposób usunięcia końcowego ukośnika z każdego parametru?


104

Jaki jest najprostszy sposób na usunięcie końcowego ukośnika z każdego parametru w tablicy „$ @”, aby rsyncskopiować katalogi według nazwy?

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

Tytuł został zmieniony w celu wyjaśnienia. Aby zrozumieć komentarze i odpowiedzieć na temat wielu końcowych ukośników, zobacz historię edycji.


Odpowiedzi:


165

Możesz skorzystać z ${parameter%word}rozszerzenia opisanego tutaj . Oto prosty skrypt testowy, który demonstruje zachowanie:

#!/bin/bash

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

echo ${@%/}

35
+1: Aby być bardzo pedantycznym, usunie to pojedynczy ukośnik, a nie wszystkie końcowe ukośniki. Aby usunąć dowolną liczbę końcowych ukośników:shopt -s extglob; echo "${@%%+(/)}"
glenn jackman

24
Ostrzeżenie: możesz nie chcieć usuwać końcowych ukośników we wszystkich przypadkach. Jeśli jako argument podano "/", usunięcie końcowego ukośnika będzie miało ... niefortunne konsekwencje.
Gordon Davisson,

13
WSKAZÓWKA: Połącz tr -s /ze zmiennym wyrażeniem regularnym, aby usunąć powtarzające się ukośniki, a następnie usuń ukośnik końcowy. np.DIR=$(echo //some///badly/written///dir////// | tr -s /); DIR=${DIR%/}
Dave

1
Naprawdę? Po usłyszeniu monitu biegnij set -- one///// two// three four/; shopt -s extglob; echo "${@%%+(/)}"i powiedz mi, co widzisz
glenn jackman

1
@twalberg Doceniam „protipsy”, które nie są tylko alternatywnymi odpowiedziami na pytanie OP w komentarzach.
Kyle Strand

40

Zaakceptowana odpowiedź spowoduje przycięcie JEDNEGO końcowego ukośnika.

Jeden ze sposobów przycinania wielu końcowych ukośników jest taki:

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

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

echo $VALUE $TRIMMED

Które wyjścia:

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

1
Nie zapomnij cytować swoich zmiennych, na wypadek gdyby zawierały spacje: TRIMMED=$(echo "$VALUE" | sed 's:/*$::')
tetsujin

1
Właściwie nie jest to konieczne wewnątrz $()konstrukcji. Jednak jest to również nieszkodliwe :), więc prawdopodobnie dobrym zwyczajem jest używanie podwójnych cudzysłowów, "$VALUE"aby nie musieć decydować, kiedy i kiedy nie używać cudzysłowów.
Chris Johnson,

Czy jest jakiś sposób na połączenie tego z wcześniejszym nagraniem? Chcę usunąć protokół i (jeśli jest obecny) końcowy ukośnik z adresu URL, ale echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)/*$|\1|'nie działa (ponieważ grupa przechwytywania pasuje również do końcowego ukośnika). Mogę to zrobić za pomocą dwóch poleceń: echo "https://www.example.com/foo/" | sed -e 's|https*://\(.*\)$|\1|' -e 's|/*$||'ale zastanawiałem się, czy można to zrobić jednym?
Adam

Ta odpowiedź działała lepiej dla mnie z bardzo dużym plikiem wejściowym. Prosty sed 's:/*$::' < in.txt > out.txtdziała w kilka sekund
MitchellK


15

realpathrozwiązuje podaną ścieżkę. Między innymi usuwa również końcowe ukośniki. Użyj, -saby zapobiec następowaniu linków SIM

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

1
Wymaga istnienia wszystkich węzłów w ścieżce z wyjątkiem ostatniego. Jeśli użytkownik wrzuci jakąś ścieżkę nieistnienia, realpathzakończy się niepowodzeniem.
Livy

2
@Livy realpath --canonicalize-missingdziała absolutnie poprawnie z każdą nieistniejącą częścią ścieżki
maoizm

a na niektórych platformach brakuje realpath :-(
Mark Ribau

8

FYI, dodałem te dwie funkcje do mojej .bash_profilena podstawie odpowiedzi znalezionych w SO. Jak powiedział Chris Johnson, wszystkie odpowiedzi za pomocą ${x%/}usuwają tylko jeden ukośnik, te funkcje zrobią to, co mówią, mam nadzieję, że będzie to przydatne.

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

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

4

W zsh możesz użyć :amodyfikatora.

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

echo "${DIRECTORY:a}"

=> /some/path/name

Działa to tak, jak, realpathale nie kończy się niepowodzeniem w przypadku braku plików / katalogów jako argumentu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.