uutils/coreutils · error · std::io::Error

mv-error-directory-not-empty

Error message

mv-error-directory-not-empty

What it means

When `rename` must move a directory onto an existing path, it removes an empty target directory; if the target is a non-empty directory it cannot proceed and raises `ErrorKind::DirectoryNotEmpty` with this message. This normalizes behavior between Unix (where rename(2) fails with ENOTEMPTY) and Windows.

Solutions

  1. Remove or empty the destination directory first (`rm -rf dest`)
  2. Use `mv src/* dest/` or `rsync -a src/ dest/ && rm -rf src` to merge contents instead
  3. Pass a fresh destination path that does not exist
  4. Script a check: `if [ -d dest ] && [ -n "$(ls -A dest)" ]; then merge; fi`

Example fix

// before
mv newlib ~/proj/lib   # lib exists and is non-empty
// after
rm -rf ~/proj/lib && mv newlib ~/proj/lib
Defensive patterns

Strategy: validation

Validate before calling

if [ -d "$dest" ] && [ -n "$(ls -A "$dest")" ]; then echo "dest not empty" >&2; exit 1; fi

Type guard

fn is_empty_dir(p: &Path) -> bool {
    std::fs::read_dir(p).map(|mut d| d.next().is_none()).unwrap_or(true)
}

Try / catch

match mv_result {
    Err(e) if e.to_string().contains("directory not empty") => {
        eprintln!("merge contents manually or clear the destination first");
    }
    r => r?,
}

Prevention

When it happens

Trigger: `mv src_dir existing_nonempty_dir` where the destination exists and contains entries, causing the pre-rename cleanup path to refuse.

Common situations: Moving a project folder onto an already-populated folder, scripts assuming mv merges directories (it does not), or leftover build/output directories in the destination.

Related errors


AI-assisted analysis of uutils/coreutils@92995feca2 (2026-09-20). Data as JSON: /api/errors/479cf3a03571cbaf. Report an issue: GitHub.

Appendix: source

Thrown at src/uu/mv/src/mv.rs:876

            // For backup renames, we don't need to track hardlinks as we're just moving the existing file
            rename_with_fallback(to, backup_path, display_manager, false, None, None)?;
        }
    }

    // "to" may no longer exist if it was backed up
    // `symlink_metadata` does not follow symlinks, so a symlink to a directory
    // is not reported as a directory, as with the previous
    // `to.exists() && to.is_dir() && !to.is_symlink()` check
    if to
        .symlink_metadata()
        .is_ok_and(|metadata| metadata.is_dir())
    {
        // normalize behavior between *nix and windows
        if from.is_dir() {
            if is_empty_dir(to) {
                fs::remove_dir(to)?;
            } else {
                return Err(io::Error::new(
                    io::ErrorKind::DirectoryNotEmpty,
                    translate!("mv-error-directory-not-empty"),
                ));
            }
        }
    }

    #[cfg(unix)]
    {
        rename_with_fallback(
            from,
            to,
            display_manager,
            opts.verbose,
            hardlink_tracker,
            hardlink_scanner,
        )?;
    }

View on GitHub (pinned to 92995feca2)