como remover a última barra do caminho do diretório?

16

Eu tenho um script que requer um diretório como um argumento. Eu quero apoiar as duas formas: uma é como

a/b/c

(sem barra no final) e outra é como

 a/b/c/

(tem barra no final).

Minha pergunta: dada uma das duas formas, como posso manter a primeira forma inalterada e remover a última barra da segunda forma para convertê-la na primeira forma.

Yulong Ao
fonte
2
Não que isso seja um grande problema - uma barra dupla em qualquer lugar, exceto no início, é equivalente a uma barra, então não se preocupe em se juntar a eles usando /.
Muru
@uru Eu não sabia disso antes :).
Yulong Ao 23/04
Aqui está uma boa Q / A em vários separadores de caminho consecutivos
Peter.O
1
@muru Uma barra no final pode fazer a diferença, como a diferença entre atuar em um link simbólico e atuar no diretório para o qual aponta ou no argumento de origem rsync.
Gilles 'SO- stop be evil'
@ Gilles de fato, mas como você pode ver, estou falando de juntar caminhos.
Muru

Respostas:

23
dir=${1%/}

pegará o primeiro parâmetro do script e removerá uma barra final, se houver.

Glenn Jackman
fonte
11

Para remover uma barra final, se houver, você pode usar a construção de expansão do parâmetro de remoção de sufixo presente em todas as shells no estilo POSIX:

x=${x%/}

Existem algumas complicações. Isso remove apenas uma barra, portanto, se você começou com a/b/c//, ainda terá uma barra. Além disso, se o caminho original era /, você precisa manter a barra. Aqui está uma solução mais complexa que cuida desses casos:

case $x in
  *[!/]*/) x=${x%"${x##*[!/]}"};;
  *[/]) x="/";;
esac

Como alternativa, em ksh ou no bash após shopt -s extglob:

[[ x = *[!/] ]] || x=${x%%*(/)}

Observe que, em muitos casos, não importa se há uma barra final. Não importa se o argumento é um link simbólico para um diretório: com uma barra final, o argumento designa o diretório, enquanto que sem barra final, o argumento designa o próprio link simbólico. Isso também é importante em alguns outros programas, por exemplo, o argumento de origem rsyncé tratado de maneira diferente, dependendo da presença de uma barra final.

Gilles 'SO- parar de ser mau'
fonte
1

realpathresolve o caminho especificado. Entre outras coisas, também remove barras à direita. Use -spara evitar seguir os simlinks

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