diff --git a/ChangeLog b/ChangeLog
index 6bfc82c0e..9820c8b4b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,7 @@ ver 0.13.0 (2007/??/??)
 * New count command for getting stats on found songs (similar to "find")
 * New playlistmove command for moving songs in stored playlists
 * New playlistdelete command for deleting songs from stored playlists
+* New rename command for renaming stored playlists
 * Lots of bug fixes, cleaned up code, and performance improvements
 
 ver 0.12.2 (2007/3/20)
diff --git a/src/command.c b/src/command.c
index c8f39472d..84a30db2b 100644
--- a/src/command.c
+++ b/src/command.c
@@ -100,6 +100,7 @@
 #define COMMAND_PLAYLISTDELETE	"playlistdelete"
 #define COMMAND_TAGTYPES	"tagtypes"
 #define COMMAND_COUNT		"count"
+#define COMMAND_RENAME		"rename"
 
 #define COMMAND_STATUS_VOLUME           "volume"
 #define COMMAND_STATUS_STATE            "state"
@@ -421,6 +422,11 @@ static int handleRm(int fd, int *permission, int argc, char *argv[])
 	return deletePlaylist(fd, argv[1]);
 }
 
+static int handleRename(int fd, int *permission, int argc, char *argv[])
+{
+	return renameStoredPlaylist(fd, argv[1], argv[2]);
+}
+
 static int handlePlaylistChanges(int fd, int *permission,
 				 int argc, char *argv[])
 {
@@ -1117,6 +1123,7 @@ void initCommands(void)
 	addCommand(COMMAND_PLAYLISTDELETE,   PERMISSION_CONTROL, 2,   2,   handlePlaylistDelete,       NULL);
 	addCommand(COMMAND_TAGTYPES,         PERMISSION_READ,    0,   0,   handleTagTypes,             NULL);
 	addCommand(COMMAND_COUNT,            PERMISSION_READ,    2,   -1,  handleCount,                NULL);
+	addCommand(COMMAND_RENAME,           PERMISSION_CONTROL, 2,   2,   handleRename,               NULL);
 
 	sortList(commandList);
 }
diff --git a/src/storedPlaylist.c b/src/storedPlaylist.c
index 8bec60e71..3559d1e2f 100644
--- a/src/storedPlaylist.c
+++ b/src/storedPlaylist.c
@@ -489,3 +489,68 @@ void appendPlaylistToStoredPlaylist(StoredPlaylist *sp, Playlist *playlist)
 		appendSongToStoredPlaylist(sp, playlist->songs[i]);
 	}
 }
+
+int renameStoredPlaylist(int fd, const char *utf8from, const char *utf8to)
+{
+	struct stat st;
+	char *from;
+	char *to;
+	int ret = 0;
+
+	from = xstrdup(utf8pathToFsPathInStoredPlaylist(utf8from, fd));
+	if (!from)
+		return -1;
+
+	to = xstrdup(utf8pathToFsPathInStoredPlaylist(utf8to, fd));
+	if (!to) {
+		free(from);
+		return -1;
+	}
+
+	if (stat(from, &st) != 0) {
+		if (fd != -1) {
+			commandError(fd, ACK_ERROR_NO_EXIST,
+			             "no playlist named \"%s\"", utf8from);
+		}
+
+		ERROR("no playlist named \"%s\"\n", utf8from);
+
+		ret = -1;
+		goto out;
+	}
+
+	if (stat(to, &st) == 0) {
+		if (fd != -1) {
+			commandError(fd, ACK_ERROR_EXIST, "a file or directory "
+			             "already exists with the name \"%s\"",
+			             utf8to);
+		}
+
+		ERROR("a file or directory already exists with the "
+		      "name \"%s\"\n", utf8to);
+
+		ret = -1;
+		goto out;
+	}
+
+	if (rename(from, to) < 0) {
+		if (fd != -1) {
+			commandError(fd, ACK_ERROR_UNKNOWN,
+			             "could not rename playlist \"%s\" to "
+			             "\"%s\": %s", utf8from, utf8to,
+			             strerror(errno));
+		}
+
+		ERROR("could not rename playlist \"%s\" to \"%s\": %s\n",
+		      utf8from, utf8to, strerror(errno));
+
+		ret = -1;
+		goto out;
+	}
+
+out:
+	free(from);
+	free(to);
+
+	return ret;
+}
diff --git a/src/storedPlaylist.h b/src/storedPlaylist.h
index 044d44ea3..1c30e814a 100644
--- a/src/storedPlaylist.h
+++ b/src/storedPlaylist.h
@@ -43,4 +43,6 @@ int writeStoredPlaylist(StoredPlaylist *sp);
 int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song);
 void appendPlaylistToStoredPlaylist(StoredPlaylist *sp, Playlist *playlist);
 
+int renameStoredPlaylist(int fd, const char *utf8from, const char *utf8to);
+
 #endif