Linux / Comando dirname: extrair a parte de diretório de um caminho

dirname extrai a parte de diretório de um caminho, retirando seu último componente. Por exemplo, dirname /home/user/report.txt produz /home/user. O comando processa texto e não confirma que o diretório existe, não resolve links simbólicos e não converte automaticamente um caminho relativo em absoluto.

Os exemplos usam a implementação de dirname do GNU Coreutils em Bash. POSIX (Portable Operating System Interface), norma de interfaces para sistemas do tipo Unix, define o formato básico com um único caminho; vários nomes e a opção -z exigem conferir a implementação. As consultas textuais abaixo podem usar caminhos fictícios, pois não acessam os arquivos indicados.

O que é o comando dirname?

Para obter a parte de um caminho completo excluindo o último componente, execute-o da seguinte forma.

dirname /home/user/report.txt

A saída é a seguinte.

/home/user

Ele não verifica se o último nome inserido é um arquivo ou diretório real. Como é um processamento simples de string, as mesmas regras se aplicam mesmo a caminhos que não existem.

Sintaxe e uso básico

dirname nome ...

Na sinopse GNU, reticências indicam que é possível repetir o argumento; não as digite literalmente. Um nome corresponde a um argumento. No exemplo abaixo, as três linhas são comandos independentes; o uso de vários argumentos em uma só chamada será mostrado adiante.

dirname /var/log/nginx/access.log
dirname /home/user/Documents/
dirname relative/path/file.txt

As saídas, na ordem, são /var/log/nginx, /home/user e relative/path. O resultado pode perder barras finais ou redundantes: não use o comando para preservar a grafia original do caminho. Ele também não substitui .. pela localização de um diretório real.

Resultados conforme a entrada

Entrada Saída geral
/home/user/report.txt /home/user
docs/manual.pdf docs
notes.txt .
/usr/ /
/ /

Nome sem barra

Sem uma barra /, o resultado é ., representação textual do diretório atual. A entrada vazia também resulta em ., conforme a especificação POSIX de dirname. Isso descreve o texto, sem localizar um arquivo:

dirname report.txt
.

Este resultado não significa que um arquivo chamado report.txt realmente exista no diretório atual; ele representa a parte do diretório na string de entrada.

Caminho absoluto e raiz

Se o último componente de um caminho absoluto for removido e apenas a raiz permanecer, / é exibido.

dirname /etc
dirname /

Ambos os comandos mostram /. A entrada especial // pode ser preservada ou tratada como /, conforme a plataforma, como explica o manual GNU de dirname. Evite presumir que dois separadores iniciais sejam equivalentes a um em todos os sistemas.

Barras finais no caminho

A barra final desnecessária é removida primeiro e, em seguida, o último componente é processado.

dirname /srv/www/site/
dirname /srv/www/site///

Os dois comandos mostram /srv/www. Retirar barras finais é parte da extração, não uma verificação de que a pasta existe ou uma normalização completa do caminho. O comando não entra na pasta nem altera a posição do terminal.

Processar vários caminhos

Informar vários nomes em uma chamada

GNU dirname aceita vários caminhos em uma única chamada. Cada argumento é processado separadamente; coloque entre aspas qualquer caminho que contenha espaços, como nos exemplos de scripts mais adiante.

dirname /srv/www/index.html /var/log/syslog /home/user/file.txt

A parte do diretório para cada entrada é exibida em uma linha separada.

/srv/www
/var/log
/home/user

Separar resultados com NUL usando -z

Quando a parte de diretório contém uma quebra de linha, separar resultados por linhas pode ser ambíguo. A opção GNU -z, ou --zero, termina cada resultado com um byte nulo, NUL. O programa que consumir esses registros também precisa aceitar esse delimitador.

dirname -z /srv/www/index.html /var/log/syslog

Este comando emite /srv/www, NUL, /var/log e NUL. Cada resultado, inclusive o último, recebe o terminador. Não guarde o fluxo NUL em uma variável Bash com $(...), pois variáveis do shell não preservam esses bytes. Verifique o suporte a -z quando precisar executar em sistemas sem GNU Coreutils.

Combinar dirname e basename

O script completo abaixo separa uma entrada em diretório e nome, sem alterar arquivos. Salve como split-path.sh e execute bash split-path.sh "/home/user/docs/report.pdf". Ele requer Bash, dirname e basename disponíveis no caminho de busca de comandos. A entrada é um argumento; a quantidade incorreta causa retorno 2 e uma falha de consulta causa retorno 1.

#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
  printf '%s\n' 'Uso: bash split-path.sh CAMINHO' >&2
  exit 2
fi
path=$1
directory=$(dirname -- "$path") || exit 1
name=$(basename -- "$path") || exit 1
printf 'Diretório: %s\n' "$directory"
printf 'Nome: %s\n' "$name"

Com o argumento indicado, a saída esperada é:

Diretório: /home/user/docs
Nome: report.pdf

O guia de basename explica a extração do último componente. As duas saídas não preservam necessariamente a escrita original de barras repetidas ou finais. Além disso, a substituição de comando remove quebras de linha finais; o script serve para exibição de nomes comuns, não para transportar fielmente todos os nomes Unix possíveis. Use um fluxo delimitado por NUL quando essa fidelidade for necessária.

Usar em scripts Bash

Preparar o diretório de um arquivo de saída

Este teste completo cria uma pasta temporária exclusiva e prepara nela o diretório de um futuro arquivo de backup. Requer Bash e os utilitários mktemp, dirname e mkdir. O teste cria apenas pastas dentro dessa área; não grava o arquivo archive.tar.gz:

(
  demo_dir=$(mktemp -d "${TMPDIR:-/tmp}/dirname-demo.XXXXXX") || exit 1
  output="$demo_dir/backups/daily/archive.tar.gz"
  output_dir=$(dirname -- "$output") || exit 1
  mkdir -p -- "$output_dir" || exit 1
  printf 'Diretório preparado: %s\n' "$output_dir"
  [ -d "$output_dir" ] && [ ! -e "$output" ]
)

A mensagem deve terminar em /backups/daily, e o teste final confirma que a pasta existe e o arquivo ainda não foi criado. A área temporária permanece para inspeção; os parênteses isolam as variáveis do terminal chamador. Em uma aplicação, dirname não valida nem restringe o destino: .., links simbólicos e alterações simultâneas de pastas exigem tratamento apropriado se a entrada vier de terceiros.

Comparar com a expansão de parâmetros

Na expansão de parâmetros do shell, ${path%/*} remove o menor sufixo que corresponda ao padrão /*. Com a entrada controlada do trecho abaixo, o resultado é /srv/www. O trecho é completo e não inicia um processo dirname:

path='/srv/www/index.html'
directory=${path%/*}
printf '%s\n' "$directory"

Essa expansão não implementa todas as regras de dirname. Para report.txt, ela mantém o nome, enquanto dirname retorna .. Para /, retorna texto vazio, enquanto dirname mantém /. Para /srv/www/site/, retira só a barra final, enquanto dirname produz /srv/www. Teste os formatos de entrada antes de trocar uma técnica pela outra.

Diferenças entre dirname, realpath e pwd

Comando Alvo para processamento Resultado principal
dirname Texto do caminho informado Parte anterior ao último componente
basename Texto do caminho informado Último nome de arquivo ou nome de diretório
realpath Caminho informado, conforme as opções Caminho normalizado, absoluto por padrão; detalhes conforme as opções
pwd Local atual de trabalho do processo Caminho absoluto do diretório de trabalho atual

dirname ../logs/app.log retorna o texto ../logs; observe o espaço entre comando e argumento. Isso não o transforma em uma localização absoluta nem resolve links. O comando pwd consulta a pasta de trabalho atual. Para normalizar outro caminho e definir como tratar links ou componentes ausentes, consulte as opções oficiais de realpath.

Opções principais

Opção Descrição
-z, --zero Termina cada resultado com um byte NUL em vez de uma nova linha.
--help Exibe o uso e as opções suportadas.
--version Imprime a versão instalada do GNU Coreutils.
-- Os argumentos subsequentes são tratados como nomes, não como opções.

O guia de comandos Linux por tarefa reúne outras ferramentas para navegação e manipulação de caminhos.

Problemas comuns

Resultado igual a um ponto

Um nome sem barra, como file.txt, não traz uma parte de diretório explícita, por isso dirname file.txt retorna .. Esse resultado não demonstra que o arquivo esteja presente no diretório atual.

Diretório extraído que não existe

dirname não verifica o sistema de arquivos. Para realmente usar o diretório de saída, você precisa verificar separadamente sua existência e permissões de acesso.

Espaços e curingas no caminho

As aspas impedem que espaços dividam um caminho em vários argumentos e que curingas sejam expandidos pelo shell. -- encerra as opções, permitindo valores que comecem com hífen. O trecho abaixo define um caminho antes da consulta:

path='/srv/uploads/annual report.pdf'
dirname -- "$path"

Perguntas frequentes

O dirname realmente encontra o diretório pai?

Não. Ele apenas remove o último componente da string do caminho de entrada; não verifica a existência real do caminho ou links simbólicos.

Por que dirname file.txt imprime um ponto único?

Sem uma barra que identifique a parte de diretório, o comando retorna ., representação do diretório atual. Isso não verifica a existência do arquivo.

É possível processar múltiplos caminhos de uma vez?

Sim, GNU dirname recebe vários caminhos e produz um resultado por argumento. O formato básico POSIX recebe um único caminho; confirme a implementação quando o script precisar funcionar em diferentes sistemas Unix.

Posso usar dirname se eu precisar de um caminho absoluto?

dirname mantém uma saída relativa quando a entrada é relativa. Se a tarefa exige uma localização absoluta normalizada, use realpath com as condições apropriadas. Para a posição atual do processo, consulte pwd.

Documentação oficial