can1357/oh-my-pi · error

{0} and {1} are the same file

Error message

{0} and {1} are the same file

What it means

GNU-compatible `mv` error (`MvError::SameFile`, crates/pi-builtins/src/mv.rs:57), raised from `assert_not_same_file`. The source and target resolve to the same file — via canonicalized paths being equal, hardlink/symlink identity detection, or the source being `.` / ending in `/.` — so moving it onto itself is a no-op that `mv` refuses.

Source

Thrown at crates/pi-builtins/src/mv.rs:57

		are_hardlinks_to_same_file, canonicalize, path_ends_with_terminator,
	},
	update_control::{self, UpdateMode},
};

use crate::host::{Host, Utility, format_usage, matches_parser, util};
#[cfg(unix)]
use self::hardlink::{
	HardlinkGroupScanner, HardlinkOptions, HardlinkTracker, create_hardlink_context,
	with_optional_hardlink_context,
};

#[derive(Debug, Error)]
enum MvError {
	#[error("cannot stat {0}: No such file or directory")]
	NoSuchFile(String),
	#[error("cannot stat {0}: Not a directory")]
	CannotStatNotADirectory(String),
	#[error("{0} and {1} are the same file")]
	SameFile(String, String),
	#[error("cannot move {0} to a subdirectory of itself, {1}")]
	SelfTargetSubdirectory(String, String),
	#[error("cannot overwrite directory {0} with non-directory")]
	DirectoryToNonDirectory(String),
	#[error("cannot overwrite non-directory {1} with directory {0}")]
	NonDirectoryToDirectory(String, String),
	#[error("target {0}: Not a directory")]
	NotADirectory(String),
	#[error("target directory {0}: Not a directory")]
	TargetNotADirectory(String),
	#[error("failed to access {0}: Not a directory")]
	FailedToAccessNotADirectory(String),
}

#[derive(Debug, Error)]
enum MvFailure {
	#[error(transparent)]

View on GitHub (pinned to 9690622007)

Solutions

  1. Skip the operation when paths are identical: compare canonical paths (`realpath`) before calling mv.
  2. Use distinct source and target names, e.g. `mv file file.bak` if a copy was intended (mv does not copy — use `cp`).
  3. Resolve symlinked directories so source and target no longer alias the same file.
  4. If the goal was moving into a directory, ensure the target is a different directory than the source's parent.

Example fix

# before
mv "$file" "$OUT_DIR/$file"   # OUT_DIR equals the file's dir -> same file
# after
src_real=$(realpath "$file"); dst_real=$(realpath -m "$OUT_DIR/$(basename "$file")")
[ "$src_real" != "$dst_real" ] && mv "$file" "$OUT_DIR/" || echo "skipping: same file"
Defensive patterns

Strategy: validation

Validate before calling

[ "$(realpath "$src")" != "$(realpath -m "$dst")" ] || { echo "same file, skipping"; exit 0; }

Try / catch

if ! mv "$src" "$dst" 2>err.txt; then grep -q 'are the same file' err.txt && exit 0; cat err.txt >&2; exit 1; fi

Prevention

When it happens

Trigger: `mv file file`; `mv ../dir/file dir/file` (same file via different relative paths); `mv . subdir` or `mv dir/. other` (source is `.` or ends with `/.`); moving a file onto a hardlink to itself; `mv x dir` where `dir` is a symlink to the directory containing `x`.

Common situations: Scripts joining an absolute base with an already-absolute path (e.g. `mv "$f" "$PWD/$f"`); symlinked directories on PATH-like setups making target and source aliases; copy-paste commands where source and target were left identical; moving directories into themselves detected here before the distinct SelfTargetSubdirectory check.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/083d5e799f65c617. Report an issue: GitHub.