0
# Directory Management
1
2
## Overview
3
4
Xonsh provides comprehensive directory navigation and management capabilities through the dirstack module. This includes traditional shell commands like `cd`, `pushd`, `popd`, and `dirs`, along with context managers for temporary directory changes.
5
6
## Directory Stack
7
8
### Core Functions
9
10
```python { .api }
11
from xonsh.dirstack import cd, pushd_fn, popd_fn, dirs_fn, DIRSTACK
12
13
def cd(args: list[str], stdin=None) -> None:
14
"""Change current directory.
15
16
Parameters
17
----------
18
args : list[str]
19
Directory arguments. First argument is target directory.
20
Supports special directories:
21
- '-': Previous directory
22
- '~': Home directory
23
- No args: Home directory
24
stdin : optional
25
Standard input (unused)
26
27
Examples
28
--------
29
cd(['/tmp']) # Change to /tmp
30
cd(['-']) # Change to previous directory
31
cd(['~']) # Change to home directory
32
cd([]) # Change to home directory
33
"""
34
35
def pushd_fn(args: list[str], stdin=None) -> None:
36
"""Push directory onto stack and change to it.
37
38
Parameters
39
----------
40
args : list[str]
41
Directory arguments or stack operations:
42
- Directory path: Push and change to directory
43
- '+N': Rotate stack bringing Nth entry to top
44
- '-N': Rotate stack bringing Nth entry from bottom to top
45
- No args: Swap top two directories
46
stdin : optional
47
Standard input (unused)
48
49
Examples
50
--------
51
pushd_fn(['/tmp']) # Push /tmp and change to it
52
pushd_fn(['+2']) # Rotate stack, bring 2nd entry to top
53
pushd_fn([]) # Swap top two directories
54
"""
55
56
def popd_fn(args: list[str], stdin=None) -> None:
57
"""Pop directory from stack and change to it.
58
59
Parameters
60
----------
61
args : list[str]
62
Stack operation arguments:
63
- '+N': Remove Nth entry from stack
64
- '-N': Remove Nth entry from bottom
65
- No args: Pop top directory and change to it
66
stdin : optional
67
Standard input (unused)
68
69
Examples
70
--------
71
popd_fn([]) # Pop top directory
72
popd_fn(['+1']) # Remove 1st entry from stack
73
popd_fn(['-0']) # Remove bottom entry from stack
74
"""
75
76
def dirs_fn(args: list[str], stdin=None) -> None:
77
"""Display directory stack.
78
79
Parameters
80
----------
81
args : list[str]
82
Display options:
83
- '-c': Clear directory stack
84
- '-p': Print one directory per line
85
- '-v': Print with line numbers
86
- '-l': Use full pathnames
87
- '+N': Display Nth entry
88
- '-N': Display Nth entry from bottom
89
stdin : optional
90
Standard input (unused)
91
92
Examples
93
--------
94
dirs_fn([]) # Show directory stack
95
dirs_fn(['-p']) # Show one per line
96
dirs_fn(['-v']) # Show with line numbers
97
dirs_fn(['-c']) # Clear directory stack
98
"""
99
100
# Global directory stack
101
DIRSTACK: list[str] # Current directory stack
102
```
103
104
## Context Managers
105
106
### Directory Context
107
108
```python { .api }
109
from xonsh.dirstack import with_pushd
110
111
def with_pushd(dirname: str):
112
"""Context manager for temporary directory changes.
113
114
Parameters
115
----------
116
dirname : str
117
Directory to change to temporarily
118
119
Returns
120
-------
121
context manager
122
Context manager that changes to dirname and restores on exit
123
124
Examples
125
--------
126
with with_pushd('/tmp'):
127
# Working in /tmp
128
print(os.getcwd()) # /tmp
129
# Back to original directory
130
"""
131
132
# Alias available in API module
133
from xonsh.api.os import indir
134
# indir is an alias to with_pushd
135
```
136
137
## Directory Stack Operations
138
139
### Stack Manipulation
140
141
```python { .api }
142
from xonsh.dirstack import DIRSTACK
143
144
# Direct stack access
145
current_stack = DIRSTACK.copy() # Get current stack
146
stack_size = len(DIRSTACK) # Stack depth
147
top_dir = DIRSTACK[0] if DIRSTACK else None # Top directory
148
149
# Stack operations through built-in functions
150
from xonsh.built_ins import XSH
151
152
# Access through shell session
153
if XSH.shell:
154
# Execute directory commands
155
XSH.execer.eval("cd /tmp")
156
XSH.execer.eval("pushd /var")
157
XSH.execer.eval("popd")
158
XSH.execer.eval("dirs")
159
```
160
161
## Advanced Directory Operations
162
163
### Path Utilities
164
165
```python { .api }
166
from xonsh.tools import expand_path, ON_WINDOWS
167
168
def expand_path(path: str) -> str:
169
"""Expand user home directory and environment variables in path.
170
171
Parameters
172
----------
173
path : str
174
Path with potential ~ or $VAR expansions
175
176
Returns
177
-------
178
str
179
Fully expanded absolute path
180
181
Examples
182
--------
183
expand_path('~/Documents') # /home/user/Documents
184
expand_path('$HOME/file.txt') # /home/user/file.txt
185
"""
186
187
# Platform-specific directory handling
188
if ON_WINDOWS:
189
# Windows-specific path handling
190
pass
191
else:
192
# Unix-like path handling
193
pass
194
```
195
196
### Directory Stack Events
197
198
```python { .api }
199
from xonsh.events import events
200
201
@events.on_chdir
202
def directory_changed(olddir: str, newdir: str) -> None:
203
"""Called when directory changes.
204
205
Parameters
206
----------
207
olddir : str
208
Previous directory
209
newdir : str
210
New current directory
211
"""
212
print(f"Changed from {olddir} to {newdir}")
213
214
# Directory change detection
215
import os
216
217
def monitor_directory_changes():
218
"""Monitor and respond to directory changes."""
219
current_dir = os.getcwd()
220
221
# Register directory change handler
222
@events.on_chdir
223
def log_dir_change(old, new):
224
with open('/tmp/dir_changes.log', 'a') as f:
225
f.write(f"Directory changed: {old} -> {new}\n")
226
```
227
228
## Integration Examples
229
230
### With Shell Commands
231
232
```python { .api }
233
# Interactive directory navigation
234
"""
235
In xonsh shell:
236
>>> cd /tmp
237
>>> pushd /var/log
238
>>> pushd /etc
239
>>> dirs -v # Show numbered stack
240
>>> popd # Back to /var/log
241
>>> popd # Back to /tmp
242
>>> cd - # Back to original directory
243
"""
244
245
# Programmatic directory operations
246
from xonsh.built_ins import XSH
247
248
def navigate_project_dirs():
249
"""Navigate through common project directories."""
250
dirs = ['/src', '/tests', '/docs', '/config']
251
252
for directory in dirs:
253
XSH.execer.eval(f"pushd {directory}")
254
# Do work in directory
255
XSH.execer.eval("popd")
256
```
257
258
### With Python Code
259
260
```python { .api }
261
import os
262
from xonsh.api.os import indir
263
264
def process_directories(dir_list: list[str]):
265
"""Process files in multiple directories."""
266
results = []
267
268
for directory in dir_list:
269
with indir(directory):
270
# Work in specific directory
271
files = os.listdir('.')
272
results.append((directory, len(files)))
273
274
return results
275
276
# Temporary directory operations
277
def backup_and_modify(target_dir: str):
278
"""Backup directory and make modifications."""
279
backup_dir = f"{target_dir}.backup"
280
281
# Create backup
282
with indir(os.path.dirname(target_dir)):
283
os.system(f"cp -r {os.path.basename(target_dir)} {backup_dir}")
284
285
# Make modifications in original
286
with indir(target_dir):
287
# Modify files in target directory
288
pass
289
```
290
291
## Directory Stack Configuration
292
293
### Environment Variables
294
295
```python { .api }
296
from xonsh.built_ins import XSH
297
298
# Configure directory stack behavior
299
env = XSH.env
300
env['CDPATH'] = '/home/user:/opt:/usr/local' # Search path for cd
301
env['AUTO_CD'] = True # Auto-cd to directory names
302
env['AUTO_PUSHD'] = True # Auto-pushd on cd
303
env['PUSHD_SILENT'] = False # Show directory after pushd
304
env['PUSHD_MINUS'] = False # Use +N instead of -N for pushd
305
```
306
307
The directory management system provides powerful navigation capabilities that integrate seamlessly with both interactive shell usage and programmatic Python operations.