or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

command-execution.mdcontrib.mderror-handling.mdindex.mdio-handling.mdprocess-management.mdutilities.md

io-handling.mddocs/

0

# Input/Output Handling

1

2

Comprehensive I/O redirection and streaming capabilities including real-time output processing, piping between commands, input feeding, and output capturing. Enables sophisticated data flow control and processing pipelines.

3

4

## Capabilities

5

6

### Real-time Output Processing

7

8

Process command output line-by-line in real-time as it's generated, enabling live monitoring and processing.

9

10

```python { .api }

11

def __call__(self, *args, _out=None, _err=None, **kwargs):

12

"""

13

Execute command with real-time output processing.

14

15

Parameters:

16

- _out: callable = function to process stdout lines

17

- _err: callable = function to process stderr lines

18

19

Returns:

20

str: Complete output (if no callback specified)

21

RunningCommand: Process object (for background execution)

22

"""

23

```

24

25

Usage examples:

26

27

```python

28

import sh

29

30

# Process output line by line

31

def handle_output(line):

32

print(f"LOG: {line.strip()}")

33

34

def handle_error(line):

35

print(f"ERROR: {line.strip()}")

36

37

# Monitor log file in real-time

38

sh.tail("-f", "/var/log/system.log", _out=handle_output, _err=handle_error)

39

40

# Process build output with custom formatting

41

def format_build_output(line):

42

if "ERROR" in line:

43

print(f"🔴 {line.strip()}")

44

elif "WARNING" in line:

45

print(f"🟡 {line.strip()}")

46

elif "SUCCESS" in line:

47

print(f"🟢 {line.strip()}")

48

else:

49

print(f"ℹ️ {line.strip()}")

50

51

sh.make("build", _out=format_build_output)

52

```

53

54

### Output Capturing and Buffering

55

56

Capture and buffer command output for later processing or analysis.

57

58

```python { .api }

59

class RunningCommand:

60

@property

61

def stdout(self) -> str:

62

"""Complete stdout output as string."""

63

64

@property

65

def stderr(self) -> str:

66

"""Complete stderr output as string."""

67

```

68

69

```python { .api }

70

def __call__(self, *args, _tee=False, **kwargs):

71

"""

72

Execute command with output capturing.

73

74

Parameters:

75

- _tee: bool/str = True to echo output to console, "out"/"err" for specific streams

76

77

Returns:

78

str: Command output

79

"""

80

```

81

82

Usage examples:

83

84

```python

85

import sh

86

87

# Capture output for processing

88

result = sh.ps("aux")

89

lines = result.split('\n')

90

python_processes = [line for line in lines if 'python' in line]

91

92

# Capture both stdout and stderr separately

93

proc = sh.grep("pattern", "file.txt", _bg=True)

94

proc.wait()

95

96

stdout_content = proc.stdout

97

stderr_content = proc.stderr

98

99

if proc.exit_code == 0:

100

print("Found matches:", stdout_content)

101

else:

102

print("Errors occurred:", stderr_content)

103

104

# Tee output (show and capture)

105

output = sh.wget("http://example.com/file.zip", _tee=True)

106

# Output is shown on console AND captured in variable

107

```

108

109

### Input Feeding

110

111

Feed input data to commands that read from stdin.

112

113

```python { .api }

114

def __call__(self, *args, _in=None, **kwargs):

115

"""

116

Execute command with input feeding.

117

118

Parameters:

119

- _in: str/bytes/file/iterable = input data to feed to command

120

121

Returns:

122

str: Command output

123

"""

124

```

125

126

Usage examples:

127

128

```python

129

import sh

130

131

# Feed string input

132

result = sh.grep("pattern", _in="line1\nline2\npattern here\nline4")

133

print(result)

134

135

# Feed file content

136

with open("input.txt", "r") as f:

137

output = sh.sort(_in=f)

138

139

# Feed data from another command's output

140

log_data = sh.cat("/var/log/system.log")

141

filtered = sh.grep("ERROR", _in=log_data)

142

143

# Feed bytes data

144

binary_data = b"binary content here"

145

result = sh.hexdump(_in=binary_data)

146

147

# Feed iterative data

148

def data_generator():

149

for i in range(1000):

150

yield f"line {i}\n"

151

152

sh.wc("-l", _in=data_generator())

153

```

154

155

### Command Piping

156

157

Chain commands together using pipes to create processing pipelines.

158

159

```python { .api }

160

def __call__(self, *args, _piped=True, **kwargs):

161

"""

162

Execute command with piping enabled.

163

164

Parameters:

165

- _piped: bool = True to enable piping output to other commands

166

167

Returns:

168

RunningCommand: Command object that can be piped to others

169

"""

170

```

171

172

Usage examples:

173

174

```python

175

import sh

176

177

# Basic piping

178

result = sh.grep(sh.ps("aux"), "python")

179

print(result)

180

181

# Complex pipeline

182

pipeline = sh.sort(sh.uniq(sh.cut(sh.cat("data.txt"), "-f", "2")))

183

print(pipeline)

184

185

# Multi-stage processing

186

logs = sh.cat("/var/log/system.log")

187

errors = sh.grep(logs, "ERROR")

188

recent_errors = sh.tail(errors, "-n", "10")

189

print(recent_errors)

190

191

# Pipeline with formatting

192

def format_ps_output(line):

193

parts = line.split()

194

if len(parts) > 10:

195

return f"PID: {parts[1]}, CMD: {parts[10]}"

196

return line

197

198

formatted = sh.ps("aux", _out=format_ps_output)

199

python_procs = sh.grep(formatted, "python")

200

```

201

202

### Stream Redirection

203

204

Redirect command streams to files or other destinations.

205

206

```python { .api }

207

def __call__(self, *args, _out_bufsize=0, _err_bufsize=0, **kwargs):

208

"""

209

Execute command with stream buffering control.

210

211

Parameters:

212

- _out_bufsize: int = stdout buffer size (0=unbuffered, 1=line-buffered)

213

- _err_bufsize: int = stderr buffer size

214

215

Returns:

216

str: Command output

217

"""

218

```

219

220

Usage examples:

221

222

```python

223

import sh

224

from io import StringIO

225

226

# Redirect to file-like objects

227

stdout_buffer = StringIO()

228

stderr_buffer = StringIO()

229

230

def write_stdout(line):

231

stdout_buffer.write(line)

232

233

def write_stderr(line):

234

stderr_buffer.write(line)

235

236

sh.make("build", _out=write_stdout, _err=write_stderr)

237

238

# Get captured content

239

build_output = stdout_buffer.getvalue()

240

build_errors = stderr_buffer.getvalue()

241

242

# Unbuffered output for real-time processing

243

sh.tail("-f", "/var/log/system.log", _out_bufsize=0, _out=lambda line: print(line, end=''))

244

```

245

246

### Advanced I/O Patterns

247

248

Complex I/O handling patterns for sophisticated data processing workflows.

249

250

```python

251

import sh

252

import threading

253

import queue

254

255

# Async output processing

256

output_queue = queue.Queue()

257

258

def queue_output(line):

259

output_queue.put(line.strip())

260

261

def process_output():

262

while True:

263

try:

264

line = output_queue.get(timeout=1)

265

# Process line here

266

print(f"Processed: {line}")

267

output_queue.task_done()

268

except queue.Empty:

269

break

270

271

# Start output processor thread

272

processor_thread = threading.Thread(target=process_output)

273

processor_thread.start()

274

275

# Run command with queued output

276

sh.find("/", "-name", "*.log", _out=queue_output, _bg=True)

277

278

# Wait for processing to complete

279

processor_thread.join()

280

281

# Filtered piping with custom logic

282

class FilteredPipe:

283

def __init__(self, filter_func):

284

self.filter_func = filter_func

285

self.buffer = []

286

287

def __call__(self, line):

288

if self.filter_func(line):

289

self.buffer.append(line.strip())

290

291

def get_results(self):

292

return '\n'.join(self.buffer)

293

294

# Filter for Python processes only

295

python_filter = FilteredPipe(lambda line: 'python' in line.lower())

296

sh.ps("aux", _out=python_filter)

297

298

python_processes = python_filter.get_results()

299

print("Python processes:")

300

print(python_processes)

301

```

302

303

### Binary Data Handling

304

305

Handle binary data streams and non-text command output.

306

307

```python { .api }

308

def __call__(self, *args, _decode_errors='strict', **kwargs):

309

"""

310

Execute command with binary data handling.

311

312

Parameters:

313

- _decode_errors: str = how to handle decode errors ('strict', 'ignore', 'replace')

314

315

Returns:

316

str/bytes: Command output

317

"""

318

```

319

320

Usage examples:

321

322

```python

323

import sh

324

325

# Handle binary output

326

binary_data = sh.cat("/bin/ls", _decode_errors='ignore')

327

print(f"Binary data length: {len(binary_data)}")

328

329

# Process binary streams

330

def handle_binary_chunk(chunk):

331

# Process binary data chunk

332

if isinstance(chunk, bytes):

333

print(f"Received {len(chunk)} bytes")

334

else:

335

print(f"Text chunk: {chunk[:50]}...")

336

337

# Commands that output binary data

338

sh.dd("if=/dev/urandom", "count=10", "bs=1024", _out=handle_binary_chunk)

339

340

# Handle mixed text/binary output

341

sh.hexdump("-C", "/bin/ls", _decode_errors='replace', _out=lambda line: print(line[:80]))

342

```