Wie eine Shell hat Vim ein Working Directory — den Kontext, von dem aus relative Pfade interpretiert werden, in dem :!command ausgeführt wird, in dem :e file.txt ohne Pfad sucht. Was viele Anfänger nicht wissen: Vim erlaubt drei Ebenen dieses Konzepts. Es gibt ein globales Working Directory, ein window-lokales und ein tab-lokales. Sauber genutzt entstehen daraus elegante Workflows: Frontend-Tab im Frontend-Verzeichnis, Backend-Tab im Backend-Verzeichnis, beide unabhängig — und jeder Split innerhalb kann sein eigenes Working Directory haben. Dazu kommt der autochdir-Mechanismus, der das Working Directory automatisch der aktuellen Datei folgen lässt, und Plugin-basierte Projekt-Root-Detection. Dieser Artikel zeigt alle drei Ebenen, das Auto-Verhalten und die typischen Konfigurations-Optionen.

Wo bin ich gerade? :pwd

Der einfachste Befehl zur Orientierung:

text :pwd
:pwd
Output
/home/user/projects/my-site

Vim zeigt das aktuell wirksame Working Directory — und das ist mehr als „wo Vim gestartet wurde". Wenn ein window-lokales oder tab-lokales Verzeichnis gesetzt ist, zeigt :pwd das wirksame Verzeichnis aus Sicht des aktuellen Fensters.

Bei einem frischen Vim-Start ist das Working Directory das Verzeichnis, in dem du Vim aufgerufen hast — analog zur Shell. Mit vim foo.txt im Verzeichnis ~/projects/site/ wird ~/projects/site/ zum initialen Vim-Working-Directory, unabhängig davon, wo foo.txt tatsächlich liegt.

Drei Ebenen: :cd, :lcd, :tcd

Vim unterscheidet drei Ebenen des Working Directory. Alle drei haben eigene :cd-Varianten:

BefehlWirkung
:cd pathglobales Working Directory wechseln — gilt für ALLE Fenster und Tabs (sofern nicht überschrieben)
:lcd pathwindow-lokales Working Directory — nur für das aktuelle Fenster
:tcd pathtab-lokales Working Directory — für alle Fenster im aktuellen Tab
:cd -zurück zum vorherigen Working Directory
:cd ~zum Home-Verzeichnis
:cd %:hzum Verzeichnis der aktuellen Datei

Die Auflösungs-Reihenfolge ist:

  1. Wenn ein window-lokales Verzeichnis gesetzt ist (per :lcd), gilt es.
  2. Sonst, wenn ein tab-lokales Verzeichnis gesetzt ist (per :tcd), gilt es.
  3. Sonst gilt das globale Verzeichnis.

Diese Hierarchie erlaubt sehr feine Setup-Varianten:

text Drei Ebenen — Beispiel-Workflow
" Vim-Start in ~/projects/myapp/
:pwd                              " /home/user/projects/myapp

" Tab 1: bleibt im Standard-Verzeichnis
" Tab 2: explizit für Frontend-Arbeit
:tabnew
:tcd frontend/
:pwd                              " .../myapp/frontend

" Tab 3: für Backend
:tabnew
:tcd backend/

" In Tab 2 einen Fenster-Split mit anderem WD:
:vsplit
:lcd ~/.config/vim/                " nur dieses Fenster ist hier
:pwd                              " ~/.config/vim
" Der ander Split in Tab 2 bleibt in frontend/

Jedes :e foo.txt, jedes :!ls, jede Tab-Completion bezieht sich nun auf das wirksame Working Directory des jeweiligen Fensters/Tabs. Eine elegante Trennung, die in Vim umgesetzt ist, in den meisten anderen Editoren aber fehlt.

autochdir — automatisch ins Datei-Verzeichnis wechseln

Wer es nicht mag, das Working Directory manuell zu pflegen, kann Vim per Option dazu bringen, automatisch ins Verzeichnis der aktuellen Datei zu wechseln, sobald sie geöffnet wird:

vim ~/.vimrc — autochdir
" Wechsle automatisch ins Verzeichnis der aktiven Datei.
" Bei jedem Buffer-Wechsel passt sich das WD an.
set autochdir

Vorteil: relative Pfade in :e, :r, :!command beziehen sich automatisch auf den Ort der aktuellen Datei. Wenn man in src/foo.go arbeitet und :e bar.go tippt, wird src/bar.go geöffnet — ohne den Pfad ausschreiben zu müssen.

Nachteil: man verliert den Kontext eines Projekt-Roots. :!grep -r pattern . wird nur im Datei-Verzeichnis suchen, nicht im gesamten Projekt. Auch Plugins, die das Working Directory zur Projekt-Erkennung nutzen, kommen ins Trudeln.

Aus diesen Gründen ist autochdir in der Praxis polarisierend. Viele User schalten es nicht ein und nutzen stattdessen explizite :cd-Befehle oder ein Projekt-Root-Plugin.

Projekt-Root-Detection ohne autochdir

Eine elegantere Alternative zu autochdir ist die Projekt-Root-Detection: Vim wechselt nicht ins Datei-Verzeichnis, sondern in das Wurzel-Verzeichnis des Projekts (typischerweise das Verzeichnis mit der .git/-Datei, einer package.json, einem go.mod etc.).

Eigene Implementierung in Vimscript

vim ~/.vimrc — eigene Root-Detection
" Suche aufwärts nach Projekt-Marker und setze WD entsprechend.
function! s:FindProjectRoot() abort
  let markers = ['.git', 'go.mod', 'package.json', 'Cargo.toml', 'pyproject.toml']
  for marker in markers
    let path = finddir(marker, expand('%:p:h') . ';')
    if !empty(path)
      return fnamemodify(path, ':h')
    endif
    let path = findfile(marker, expand('%:p:h') . ';')
    if !empty(path)
      return fnamemodify(path, ':h')
    endif
  endfor
  return expand('%:p:h')
endfunction

" Auto-Wechsel bei BufEnter
autocmd BufEnter * silent! execute 'lcd ' . fnameescape(<SID>FindProjectRoot())

Diese Funktion sucht ausgehend vom Verzeichnis der aktuellen Datei aufwärts nach einer der Marker-Dateien — .git, go.mod, package.json, Cargo.toml, pyproject.toml. Sobald gefunden, wird ihr Verzeichnis als Projekt-Root verwendet und per :lcd als window-lokales Working Directory gesetzt.

Mit :lcd (statt :cd) bleibt das pro Fenster, sodass mehrere Splits parallel in unterschiedlichen Projekten arbeiten können.

Plugin: vim-rooter

Wer keine eigene Funktion schreiben will, nutzt das Plugin airblade/vim-rooter. Es macht genau das Gleiche — mit konfigurierbaren Markern und sauber gewartet:

vim ~/.vimrc — vim-rooter
" vim-rooter installieren (mit vim-plug oder Manager der Wahl)
Plug 'airblade/vim-rooter'

" Marker für Projekt-Roots
let g:rooter_patterns = ['.git', 'go.mod', 'package.json', 'Cargo.toml']

" Statt globalem :cd: window-lokales :lcd
let g:rooter_cd_cmd = 'lcd'

" Stille (kein Echo bei Wechsel)
let g:rooter_silent_chdir = 1

vim-rooter ist die pragmatische Default-Wahl, wenn man eine zuverlässige Projekt-Root-Detection ohne eigene Vimscript-Implementierung möchte. Drei Zeilen Konfig, fertig.

Working Directory in der Statusline

Eine kleine Komfort-Verbesserung: das aktuelle Working Directory in der Statusline anzeigen — damit ist die Antwort auf „wo bin ich gerade?" immer sichtbar, ohne :pwd zu tippen.

vim ~/.vimrc — WD in Statusline
" Default-Statusline um WD ergänzen
" %{getcwd()} expandiert zur Laufzeit das aktuelle Working Directory
set statusline=%f\ %m%r%h%w\ \|\ %{getcwd()}\ \|\ %=%l/%L,%c

" Statusline immer anzeigen (Default ist „nur bei mehreren Fenstern&quot;)
set laststatus=2

Mit einem Statusline-Plugin wie vim-airline oder lightline ist diese Information meist schon Default — siehe Kapitel UI und Statusline.

Praxis-Workflows

Drei typische Anwendungs-Szenarien:

Workflow 1: zwei Projekte parallel in einer Vim-Session

text Workflow 1
" Tab 1: Projekt A
:tcd ~/projects/site
:e index.html

" Tab 2: Projekt B — eigenes WD
:tabnew
:tcd ~/projects/api
:e main.go

" Wechsel zwischen Tabs (gt/gT) — jeder Tab hat sein eigenes WD.
" :e bar.txt in Tab 1 öffnet ~/projects/site/bar.txt
" :e bar.txt in Tab 2 öffnet ~/projects/api/bar.txt

Workflow 2: kurzer Sprung in ein Konfig-Verzeichnis

text Workflow 2
" In einem Code-Tab arbeitend, kurz die Konfig editieren:
:vsplit
:lcd ~/.config/vim/
:e vimrc

" Der ursprüngliche Split bleibt im Projekt-WD,
" nur dieses Fenster ist in ~/.config/vim/.
" Nach Schließen des Splits ist man wieder im Projekt.

Workflow 3: Shell-Befehl im Projekt-Root, egal welche Datei aktiv

Mit Projekt-Root-Detection (vim-rooter oder eigene Implementierung) ist :!command automatisch im Projekt-Root — egal in welchem Unterverzeichnis die aktive Datei liegt.

text Workflow 3
" Aktive Datei: src/auth/handler.go
" WD (per vim-rooter): /home/user/projects/myapp (Projekt-Root)

:!go test ./...       " läuft im Projekt-Root, testet alle Pakete
:!git status          " zeigt Status für das ganze Projekt
:!make build          " ruft das Top-Level-Makefile auf

Ohne Root-Detection (oder mit autochdir) müsste man manuell ins Projekt-Root cd-en — was den Workflow regelmäßig unterbricht.

getcwd() und Vimscript-Zugriff

Für eigene Mappings und Funktionen ist getcwd() der Vimscript-Zugriff aufs Working Directory:

AufrufErgebnis
getcwd()aktuelles wirksames WD
getcwd(-1, -1)globales WD (ignoriert lcd/tcd)
getcwd(0)window-lokales WD (oder leer, falls keins gesetzt)
getcwd(0, 0)tab-lokales WD (oder leer)
haslocaldir()1 wenn aktuelles Fenster ein lokales WD hat, 0 sonst
haslocaldir(0, 0)2 wenn tab-lokales WD gesetzt ist

Praktisches Beispiel — eine Mapping, das den Buffer-Inhalt mit dem Working-Directory-Pfad als Header oben einfügt:

vim ~/.vimrc — WD-Pfad in Datei einfügen
" <leader>ip = insert path (Projekt-Root als Kommentar)
nnoremap <leader>ip :put = '// Project root: ' . getcwd()<CR>

FAQ

Was ist der Unterschied zwischen `:cd` und `:lcd`?

:cd ändert das globale Working Directory — alle Fenster und Tabs sind danach im neuen Verzeichnis (sofern sie kein eigenes lokales gesetzt haben). :lcd ändert nur das aktuelle Fenster — andere Fenster bleiben, wo sie waren. Für gemischte Setups ist :lcd fast immer die saubere Wahl.

`autochdir` und Projekt-Root-Detection schließen sich aus

autochdir wechselt ins Datei-Verzeichnis, vim-rooter ins Projekt-Root. Beide gleichzeitig aktiv führt zu Konflikten — meistens „wer-zuletzt-kam-mahlt-zuerst". Entscheide dich für eines.

`:pwd` zeigt das wirksame WD aus aktuellem Kontext

Wenn ein window-lokales WD gesetzt ist, zeigt :pwd dieses — nicht das globale. Wer prüfen will, welche Ebene gerade greift, nutzt getcwd(0) (window) und haslocaldir() (1 = window-lokal, 2 = tab-lokal, 0 = global).

Backticks im Pfad für dynamische Werte

`:cd ``git rev-parse --show-toplevel``` wechselt ins Git-Root des aktuellen Verzeichnisses — eine schnelle, plugin-freie Variante der Projekt-Root-Detection. Geht aber nur, wenn die aktuelle Datei in einem Git-Repo liegt.

Tab-lokales WD überlebt Split-Operationen

Mit :tcd gesetzte tab-lokale Verzeichnisse gelten für alle Fenster im Tab — auch für solche, die später per :split/:vsplit hinzukommen. Wer einen Tab als eigenen Workspace betrachtet, sollte das WD per :tcd setzen, nicht per :lcd.

`:cd -` ist „back to where you came from"

Analog zur Shell wechselt :cd - zurück zum vorherigen Working Directory. Praktisch beim kurzen Abstecher in ein Konfig-Verzeichnis und schneller Rückkehr.

Weiterführende Ressourcen

Externe Quellen

Verwandte Artikel

/ Weiter

Zurück zu Dateien & Verzeichnisse

Zur Übersicht