Skip to content

Commit

Permalink
v1.5: /files and /dirs options added
Browse files Browse the repository at this point in the history
  • Loading branch information
nicjansma committed Sep 1, 2020
1 parent 184f0cb commit 5817e8e
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 80 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
source/bin
source/obj
source/StyleCop.Cache
*.suo
.vs/
31 changes: 23 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
Copyright (c) 2018 Nic Jansma
Copyright (c) 2020 Nic Jansma
[http://nicj.net](http://nicj.net)

# Introduction

RenameRegex (RR) is a Windows command-line bulk file renamer, using regular expressions. You can use it as a simple
RenameRegex (RR) is a Windows command-line bulk file and directory renamer, using regular expressions. You can use it as a simple
file renamer or with a complex regular expression for matching and replacement. See the Examples section for details.

# Usage

RR.exe file-match search replace [/p] [/r] [/f] [/e]
/p: pretend (show what will be renamed)
/r: recursive
/f: force overwrite if the file already exists
/e: preserve file extensions
```
RR.exe file-match search replace [/p] [/r] [/f] [/e] [/files] [/dirs]
/p: pretend (show what will be renamed)
/r: recursive
/f: force overwrite if the file already exists
/e: preserve file extensions
/files: include only files
/dirs: include only directories
(default is to include files only, to include both use /files /dirs)
```

You can use [.NET regular expressions](http://msdn.microsoft.com/en-us/library/hs600312.aspx) for the search and
replacement strings, including [substitutions](http://msdn.microsoft.com/en-us/library/ewy2t5e0.aspx) (for example,
Expand All @@ -36,15 +41,25 @@ Rename files in the pattern of "`124_xyz.txt`" to "`xyz_123.txt`":

RR.exe *.txt "([0-9]+)_([a-z]+)" "$2_$1"

Rename directories (only)

RR * "-" "_" /dirs

Rename files and directories

RR * "-" "_" /files /dirs

# Version History

* v1.0 - 2012-01-30: Initial release
* v1.1 - 2012-12-15: Added /r option
* v1.2 - 2013-05-11: Allow /p and /r options before or after main arguments
* v1.3 - 2013-10-23: Added /f option
* v1.4 - 2018-04-06: Added /e option via Marcel Peeters
* v1.4 - 2018-04-06: Added /e option (via Marcel Peeters)
* v1.5 - 2020-07-02: Added support for directories, added length-check (via Alec S. @Synetech)

# Credits

* Nic Jansma (http://nicj.net)
* Marcel Peeters
* Alec S. (http://synetech.freehostia.com/)
Binary file modified bin/RR.exe
Binary file not shown.
96 changes: 83 additions & 13 deletions source/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// <copyright file="Program.cs" company="Nic Jansma">
// Copyright (c) Nic Jansma 2013 All Right Reserved
// Copyright (c) Nic Jansma 2020 All Right Reserved
// </copyright>
// <author>Nic Jansma</author>
// <email>nic@nicj.net</email>
namespace RenameRegex
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
Expand All @@ -16,6 +17,21 @@ namespace RenameRegex
/// </summary>
public static class Program
{
/// <summary>
/// Maximum Windows / DOS path length
/// </summary>
public const int MaxPath = 260;

/// <summary>
/// Include files
/// </summary>
public const int IncludeFiles = 1;

/// <summary>
/// Include directories
/// </summary>
public const int IncludeDirs = 2;

/// <summary>
/// Main command line
/// </summary>
Expand All @@ -31,6 +47,7 @@ public static int Main(string[] args)
bool pretend;
bool force;
bool preserveExt;
int includeMask;

if (!GetArguments(
args,
Expand All @@ -40,21 +57,43 @@ public static int Main(string[] args)
out pretend,
out recursive,
out force,
out preserveExt))
out preserveExt,
out includeMask))
{
Usage();

return 1;
}

// enumerate all files
string[] files = Directory.GetFiles(
System.Environment.CurrentDirectory,
fileMatch,
recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
// enumerate all files and directories
List<string> allItems = new List<string>();

// include all files by default
if ((includeMask == 0) || ((includeMask & IncludeFiles) != 0))
{
string[] files = Directory.GetFiles(
Environment.CurrentDirectory,
fileMatch,
recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

allItems.AddRange(files);
}

if (files.Length == 0)
// include all directories if requested
if ((includeMask & IncludeDirs) != 0)
{
Console.WriteLine(@"No files match!");
string[] dirs = Directory.GetDirectories(
Environment.CurrentDirectory,
fileMatch,
recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);

allItems.AddRange(dirs);
}

if (allItems.Count == 0)
{
Console.WriteLine(@"No files or directories match!");

return 1;
}

Expand All @@ -63,8 +102,14 @@ public static int Main(string[] args)
//
// loop through each file, renaming via a regex
//
foreach (string fullFile in files)
foreach (string fullFile in allItems)
{
if (fullFile.Length > MaxPath || Path.GetDirectoryName(fullFile).Length > MaxPath - 12)
{
Console.WriteLine(@"""{0}"" cannot be accessed; too long.", fullFile);
continue;
}

// split into filename, extension and path
string fileName = Path.GetFileNameWithoutExtension(fullFile);
string fileExt = Path.GetExtension(fullFile);
Expand Down Expand Up @@ -117,7 +162,18 @@ public static int Main(string[] args)
File.Delete(fileNameAfter);
}

File.Move(fileDir + @"\" + fileName, fileDir + @"\" + fileNameAfter);
if (File.Exists(fileName))
{
File.Move(fileDir + @"\" + fileName, fileDir + @"\" + fileNameAfter);
}
else if (Directory.Exists(fileName))
{
Directory.Move(fileDir + @"\" + fileName, fileDir + @"\" + fileNameAfter);
}
else
{
Console.WriteLine(@"Could not rename {0}", fileName);
}
}
catch (IOException)
{
Expand All @@ -140,6 +196,7 @@ public static int Main(string[] args)
/// <param name="recursive">Whether or not to recursively look in directories</param>
/// <param name="force">Whether or not to force overwrites</param>
/// <param name="preserveExt">Whether or not to preserve file extensions</param>
/// <param name="includeMask">Whether to include directories, files or both</param>
/// <returns>True if argument parsing was successful</returns>
private static bool GetArguments(
string[] args,
Expand All @@ -149,7 +206,8 @@ public static int Main(string[] args)
out bool pretend,
out bool recursive,
out bool force,
out bool preserveExt)
out bool preserveExt,
out int includeMask)
{
// defaults
fileMatch = String.Empty;
Expand All @@ -162,6 +220,7 @@ public static int Main(string[] args)
recursive = false;
force = false;
preserveExt = false;
includeMask = 0;

// check for all arguments
if (args == null || args.Length < 3)
Expand Down Expand Up @@ -196,6 +255,14 @@ public static int Main(string[] args)
{
preserveExt = true;
}
else if (args[i].Equals("/files", StringComparison.OrdinalIgnoreCase))
{
includeMask |= IncludeFiles;
}
else if (args[i].Equals("/dirs", StringComparison.OrdinalIgnoreCase))
{
includeMask |= IncludeDirs;
}
else
{
// if not an option, the rest of the arguments are filename, search, replace
Expand Down Expand Up @@ -233,11 +300,14 @@ private static void Usage()

Console.WriteLine(@"Rename Regex (RR) v{0} by Nic Jansma, http://nicj.net", version);
Console.WriteLine();
Console.WriteLine(@"Usage: RR.exe file-match search replace [/p] [/r] [/f] [/e]");
Console.WriteLine(@"Usage: RR.exe file-match search replace [/p] [/r] [/f] [/e] [/files] [/dirs]");
Console.WriteLine(@" /p: pretend (show what will be renamed)");
Console.WriteLine(@" /r: recursive");
Console.WriteLine(@" /f: force overwrite if the file already exists");
Console.WriteLine(@" /e: preserve file extensions");
Console.WriteLine(@" /files: include files (default)");
Console.WriteLine(@" /dirs: include directories");
Console.WriteLine(@" (default is to include files only, to include both use /files /dirs)");
return;
}
}
Expand Down
14 changes: 7 additions & 7 deletions source/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// <copyright file="AssemblyInfo.cs" company="Nic Jansma">
// Copyright (c) Nic Jansma 2013 All Right Reserved
// <copyright file="AssemblyInfo.cs" company="Nic Jansma">
// Copyright (c) Nic Jansma 2020 All Right Reserved
// </copyright>
// <author>Nic Jansma</author>
// <email>nic@nicj.net</email>
Expand All @@ -12,11 +12,11 @@
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("RenameRegex")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyDescription("Use regular-expressions to rename files and directories from the command-line")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RenameRegex")]
[assembly: AssemblyCopyright("Copyright © Nic Jansma 2013")]
[assembly: AssemblyCopyright("Copyright © Nic Jansma 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -34,8 +34,8 @@
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.4.0.0")]
[assembly: AssemblyFileVersion("1.4.0.0")]
//
[assembly: AssemblyVersion("1.5.0.0")]
[assembly: AssemblyFileVersion("1.5.0.0")]

[assembly: CLSCompliant(true)]
25 changes: 25 additions & 0 deletions source/RenameRegex.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.1209
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenameRegex", "RenameRegex.csproj", "{16A6043E-7F40-476D-B063-F3F9A2351C36}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{16A6043E-7F40-476D-B063-F3F9A2351C36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16A6043E-7F40-476D-B063-F3F9A2351C36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16A6043E-7F40-476D-B063-F3F9A2351C36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16A6043E-7F40-476D-B063-F3F9A2351C36}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {35B6CC6D-E147-4D40-B2D7-7D18C57A0B25}
EndGlobalSection
EndGlobal
52 changes: 0 additions & 52 deletions source/StyleCop.Cache

This file was deleted.

0 comments on commit 5817e8e

Please sign in to comment.