CLAUDE LABJP
2.1.273 — A round of connection work landed together: five opt-in headers for LLM gateways, and a notice when Claude Code stops trying to reconnect an MCP server09/29 — The date beside claude-sonnet-4-5 is 12 days out, but it is an earliest-possible estimate. The model is still Active, and public retirements get at least 60 days noticeMCP — People keep asking to reconnect a dropped server without ending the session. The disconnect is now announced, but reattaching is still something you do by handNEW — A scheduled task ran some days and not others. The cause was that only one folder had been bound to itWINDOWS — When Cowork fails on its very first task, check developer mode and the setup state before going looking for a causeHANDOFF — Before a long draft gets too heavy for one chat, decide on the three things the summary must carry into the next one2.1.273 — A round of connection work landed together: five opt-in headers for LLM gateways, and a notice when Claude Code stops trying to reconnect an MCP server09/29 — The date beside claude-sonnet-4-5 is 12 days out, but it is an earliest-possible estimate. The model is still Active, and public retirements get at least 60 days noticeMCP — People keep asking to reconnect a dropped server without ending the session. The disconnect is now announced, but reattaching is still something you do by handNEW — A scheduled task ran some days and not others. The cause was that only one folder had been bound to itWINDOWS — When Cowork fails on its very first task, check developer mode and the setup state before going looking for a causeHANDOFF — Before a long draft gets too heavy for one chat, decide on the three things the summary must carry into the next one
Articles/Claude Code
Claude Code/2026-08-25Intermediate

One Space in a Folder Name Turned 80 Checks Into Zero

An inspection loop reported 80 files checked and 0 readable. The files were fine. Here is how word splitting turns path fragments into real directories, measured side by side, plus the count assertion I now put in front of every delete-heavy batch.

Claude Code253bash5automation110indie development23operations29

Premium Article

I wanted a quick pass over the documents scattered through a working folder, so I wrote a short loop: match by extension, read the first byte, count what opens. Roughly 80 files.

It printed this.

checked=80 readable=0 unreadable=80

Eighty files checked, none readable. My first suspicion was sync. The folder lives under cloud storage, so I assumed the contents had not been materialized yet.

But opening any one of them with cat worked fine. Nothing was missing.

The files were never the problem. The folder name contained a single space. That was the whole story.

The 80 files had become 160 iterations

The loop looked like this — probably the most commonly written shape in personal inspection scripts.

for f in $(find "$ROOT/_documents" -type f -name "*.md"); do
  if head -c 1 "$f" >/dev/null 2>&1; then ok=$((ok+1)); else ng=$((ng+1)); fi
done

"$ROOT/_documents" is quoted. The loop variable "$f" is quoted. It still breaks.

What breaks is outside the $( ). The result of a command substitution sits in an unquoted position, so the shell splits it on IFS — space, tab, newline by default. A single line of output from find gets torn in two at the space.

Here is the measurement. Eighty 100-byte files under a directory whose name contains a space, same loop:

=== A: unquoted command substitution ===
iterations=160 readable=0 unreadable=160  (actual file count: 80)

One hundred sixty iterations — exactly twice the file count. Each path split into two fragments, and the loop treated each fragment as a filename. Neither half opens, naturally.

Switch to NUL-delimited output and the picture changes:

while IFS= read -r -d '' f; do
  head -c 1 "$f" >/dev/null 2>&1 && ok=$((ok+1))
done < <(find "$ROOT/_documents" -type f -name "*.md" -print0)
=== B: find -print0 + while read -d '' ===
iterations=80 readable=80 unreadable=0

All 80. The files had been readable the entire time.

When a fragment turns into a real path

So far this is only a missed read. What actually made me sit up was the next test.

The leading fragment of a split path can be a directory that exists.

Split /work/Dolice Labs/out/tmp_1.txt and the first half is /work/Dolice. If a folder named Dolice happens to live at that level, the fragment does not point at nothing. It points at somewhere real.

To check, I put 5 files I wanted deleted in Dolice Labs/out/ and 3 files that must survive in Dolice/keep/, then ran the naive loop with a delete in it.

for f in $(find "$T/Dolice Labs/out" -type f -name "tmp_*.txt"); do
  rm -rf "$f" 2>/dev/null
done

The result:

before: keep=3 tmp=5
after : keep=0 tmp=5
TargetIntentBeforeAfter
Dolice Labs/out/delete these55 (nothing deleted)
Dolice/keep/never touch these30 (all gone)

Not one intended file was removed, and the side that should have been untouched was wiped. The loop exited 0 and printed nothing to stderr.

Note that rm -rf "$f" is quoted. Quoting only guarantees that the fragment arrives as a single argument. It says nothing about where that fragment points. That is the core of this failure.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Be able to tell, in a few minutes, whether a batch script running under a path with spaces is quietly skipping every file
Be able to separate 'nothing matched' from 'nothing could be opened' mechanically, by reconciling expected and processed counts
Be able to decide where a guard belongs in a delete-heavy batch, based on a run that kept all 5 files it meant to delete and removed all 3 it was supposed to leave alone
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Claude Code2026-08-31
Half of My Scheduled Runs Vanished Without a Single Error
A batch job set to run twice a day was only firing once. No errors, no failure alerts. Here is how to expand your own schedule, count expected runs, and reconcile them against execution records to catch silent misses.
Claude Code2026-08-04
Tightening Filesystem Isolation Separately from the Network — Collect the Paths, Then Squeeze the Write Surface
Claude Code v2.1.216 lets you control filesystem isolation independently from network isolation. Before tightening anything, I traced what a real job actually touches, split reads from writes, and measured how stable the path set is across repeated runs. The numbers changed how I wrote the allowlist.
Claude Code2026-06-17
The Day a Billing Change Got Reversed at the Last Minute — Designing a Reversible Pipeline So You Don't Rewrite in a Panic
A billing change due to take effect on June 15 was retracted at the eleventh hour. From the position of someone who had literally logged 'effective today' the night before, here is why I didn't have to scramble to rewrite my headless stages, and how to build a pipeline that survives reversals and delays — with working code.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links