diff --git a/compiler/test/stdlib/path.test.gr b/compiler/test/stdlib/path.test.gr
index 99ae147694..5a3c755c56 100644
--- a/compiler/test/stdlib/path.test.gr
+++ b/compiler/test/stdlib/path.test.gr
@@ -277,3 +277,11 @@ assert Path.ancestry(fs("../dir1"), fs("./dir2")) == Ok(Path.NoLineage)
assert Path.ancestry(fs("./dir1"), fs("../../dir2")) == Ok(Path.NoLineage)
assert Path.ancestry(fs("./dir1"), fs("/dir2")) == Err(Path.DifferentBases)
assert Path.ancestry(fs("C:/dir1"), fs("/dir2")) == Err(Path.DifferentRoots)
+
+// Path.removeExtension
+assert Path.removeExtension(fs("file.txt")) == fs("file")
+assert Path.removeExtension(fs("file")) == fs("file")
+assert Path.removeExtension(fs("file.tar.gz")) == fs("file")
+assert Path.removeExtension(fs("/test/")) == fs("/test/")
+assert Path.removeExtension(fs("/test/test")) == fs("/test/test")
+assert Path.removeExtension(fs(".gitignore")) == fs(".gitignore")
diff --git a/stdlib/path.gr b/stdlib/path.gr
index e106f5d4b8..7b7b9dde8f 100644
--- a/stdlib/path.gr
+++ b/stdlib/path.gr
@@ -722,6 +722,29 @@ provide let extension = (path: Path) => {
}
}
+/**
+ * Removes the extension from a path, if there is no extension, returns the path as is.
+ *
+ * @param path: The path to modify
+ * @returns The path with the extension removed
+ *
+ * @example removeExtension(fromString("file.txt")) == fromString("file")
+ * @example removeExtension(fromString(".gitignore")) == fromString(".gitignore")
+ * @example removeExtension(fromString("./dir/file")) == fromString("dir/file")
+ * @example removeExtension(fromString("./dir/")) == fromString("dir/")
+ *
+ * @since v7.0.0
+ */
+provide let removeExtension = (path: Path) => {
+ match (pathInfo(path)) {
+ (base, File, [name, ...rest]) as pathInfo => {
+ let (name, _) = stemExtHelper(pathInfo)
+ toPath((base, File, [name, ...rest]))
+ },
+ _ => path,
+ }
+}
+
// should only be used on absolute paths
let rootHelper = (path: PathInfo) => match (path) {
(Abs(root), _, _) => root,
diff --git a/stdlib/path.md b/stdlib/path.md
index 177373022d..7b08cce11d 100644
--- a/stdlib/path.md
+++ b/stdlib/path.md
@@ -637,6 +637,49 @@ extension(fromString(".a.tar.gz")) == Ok(".tar.gz")
extension(fromString("/dir/")) == Err(IncompatiblePathType) // can only take extension of a file path
```
+### Path.**removeExtension**
+
+
+Added in next
+No other changes yet.
+
+
+```grain
+removeExtension : (path: Path) => Path
+```
+
+Removes the extension from a path, if there is no extension, returns the path as is.
+
+Parameters:
+
+|param|type|description|
+|-----|----|-----------|
+|`path`|`Path`|The path to modify|
+
+Returns:
+
+|type|description|
+|----|-----------|
+|`Path`|The path with the extension removed|
+
+Examples:
+
+```grain
+removeExtension(fromString("file.txt")) == fromString("file")
+```
+
+```grain
+removeExtension(fromString(".gitignore")) == fromString(".gitignore")
+```
+
+```grain
+removeExtension(fromString("./dir/file")) == fromString("dir/file")
+```
+
+```grain
+removeExtension(fromString("./dir/")) == fromString("dir/")
+```
+
### Path.**root**