I'm looking for a way to scramble/unscramble (encrypt/decrypt) the filenames of every file in a directory via batch script. One .bat file would encrypt the filenames in the current directory, and another would decrypt them.
I have an idea as to how this might work, but lack the batch file skills/experience to make it happen on my own: Have the encryption script find the ASCII value of each character in each filename, increment each character by a certain amount, and then rename each file accordingly. The decryption script would function in a similar but opposite manner. Just an idea - as long as the filename gets fully scrambled and unscrambled, I will be happy.
Any batch file wizards out there willing to lend a hand? Thanks in advance!
Here is a solution that utilizes JREPL.BAT - a regular expression find/replace utility. JREPL is pure script (hybrid JScript/batch) that runs natively on any windows machine from XP onward - no 3rd party exe required.
I used the simple ROT13 substitution cipher Running the script once encrypts the names. Running a second time restores the names to the original values. I chose to encrypt only the file name, not the extension. It would be easy to modify to encrypt the extension as well.
encryptNames.bat
#echo off
pushd %1 .
call :sub
popd
exit /b
:sub Subroutine needed to guarantee %-f0 gives the correct value
setlocal
set "find=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
set "repl=NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
set "p=/(.*)/"
set "prepl={$1}"
for /f "delims=" %%C in (
'cmd /c "for %%F in (*) do #if "%%~fF" neq "%~f0" echo ren "%%F" "/%%~nF/%%~xF""^|jrepl find repl /t "" /p p /prepl "{$1}" /v'
) do echo %%C&%%C
Calling encryptNames.bat without any argument will encrypt all files in the current directory (except for the encryptNames.bat file itself)
You can encrypt the names in any folder by passing the folder path as an argument. For example:
encryptNames c:\my\folder\to\be\encrypted
Note that encryptNames.bat assumes JREPL.BAT is in a folder that is listed within your PATH environment variable. If you put JREPL.BAT in the same folder as encryptNames.bat, and then encrypt the files in that folder, then JREPL.BAT will be encrypted, and you will no longer be able to run encryptNames.bat!
Related
I am trying to iterate files in a folder and process them with another batch file inside the do loop. It works with echo but as soon as I use the variable as input to the program, it echoes the () part and everything inside.
Here's what I'm trying to do.
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
for /r %%f in (/folder/*) do (
set name="%%~nf"
echo !name! <--- ok
process.bat !name! <--- echoes () and commands inside this do loop
)
ENDLOCAL
The process.bat just capitalizes the first letter of the filename and echoes it for debug or confirmation.
A batch file must be called from within a batch file using command call as otherwise Windows command processor continues processing on other batch file with never returning back to initial batch file.
See also: How to call a batch file that is one level up from the current directory?
Please read excellent answer on batch file echo on/off not working properly written by dbenham for the reason on getting suddenly the commands executed by FOR output after first execution of process.bat without using command CALL. I cannot explain better what happens in this case.
The directory separator on Windows is the backslash character \ and not the forward slash / as on Linux or Mac. Windows supports also / in file/folder paths for compatibility reasons by automatically replacing all / by \ before accessing the Windows file systems, but a good written script uses 100% correct syntax and does not depend on automatic corrections done by other programs. / is used on Windows mainly for command line switches.
The usage of / instead of \ can result in an unexpected behavior. For example run a batch file with following content:
#echo off
echo Files in directory %SystemRoot:\=/%/:
for %%I in (%SystemRoot:\=/%/*) echo %%I
echo/
pause
echo/
echo Files in directory %SystemRoot%\:
for %%I in (%SystemRoot%\*) echo %%I
echo/
pause
The first FOR using C:/Windows/* as wildcard pattern outputs the file names with just drive letter + colon + file name + file extension. The file path \Windows\ is missing in output file names. The second FOR loop using C:\Windows\* as wildcard pattern outputs the full qualified file names, i.e. drive letter + colon + file path + file name + file extension.
A file/folder path starting with \ references a directory or file relative to root directory of current DRIVE.
This is explained by the Microsoft documentation Naming Files, Paths, and Namespaces.
It looks like folder is a subdirectory in directory of the executed batch file. In this case / or \ at beginning of folder path is definitely not correct. The backslash at beginning can be omitted or .\ is used to reference the directory folder in current directory on execution of the batch file. But the current directory on batch file execution can be also different to directory containing the executed batch file, for example on running the batch file as administrator, or on running the batch file as scheduled task, or on running the batch file from a network resource accessed using a UNC path. For that reason it is advisable to reference explicitly subdirectory folder in directory of the batch file.
Delayed environment variable expansion is not needed as long as the file name assigned currently to the loop variable does not need to be modified other than the modifiers of for support it. A command line like set name="%%~nf" does not work correct with enabled delayed expansion and file name contains one or more ! because of cmd.exe interprets the exclamation mark(s) in file name as beginning/end of a delayed expanded environment variable reference.
See also: How does the Windows Command Interpreter (CMD.EXE) parse scripts?
It looks like a recursive search for non-hidden files is not really needed as otherwise passing just file name without path and file extension would be not enough to get the right file processed by other batch file process.bat.
So the entire task can be done most likely also with:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for %%I in ("%~dp0folder\*") do call "%~dp0process.bat" "%%~nI"
endlocal
But if the other batch file process.bat expects that the passed file name without file extension and path is in current directory on execution of process.bat, it is necessary to make the subdirectory folder in directory of this batch file first the current directory.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0folder"
for %%I in (*) do call "%~dp0process.bat" "%%~nI"
popd
endlocal
Note: The batch file folder path referenced with %~dp0 always ends with a backslash. Therefore no additional backslash should be used on concatenating this path string with a file/folder name to avoid having finally on execution of the batch file \\ in full qualified file/folder name, although Windows kernel corrects such paths also automatically by removing second backslash in this case.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
endlocal /?
popd /?
pushd /?
set /?
setlocal /?
I regularly have to rename hundreds of files across a subfolder structure. I have been creating a batch file consisting of all my rename commands, and manually pasting this into each subfolder to execute one subfolder at a time. I'd like to revise the batch script so that it executes against all subfolders in one fell swoop, run from the parent directory just once.
My renaming is very manual, and so I need to create a discrete entry for each file. For example, here are three lines:
REN STWP01_00669087* BCBSRI-01849351*
REN BCBSRI-01849357* 2011-12-19_BCBSRI-01849357*
REN STWP01_00669094* BCBSRI-01849369*
I've experimented with the FOR /R command, including trying a separate batch file that calls my renaming batch file (via the CALL command). No luck.
I have to assume that this is simple, but I'm a batch novice, so any help would be appreciated.
Thanks!
#Magoo,
Thanks so much for your response. Your approach is going to be far more efficient than my own so far.
A couple of questions. Please bear with me as I am a total novice with batch commands.
Here's what I did: I saved your code to a .BAT file ("RRename.bat"), modified my filenames as per your instructions and saved those to a text file ("Filenames.txt"), and then run this command from the command line: {RRename.bat Filenames.txt}.
The resulting command windows confirm correct renaming. And so I removed the ECHO and PAUSE commands and re-ran. No luck. Just a bunch of Command windows confirming the directory.
Ideally I'd love to save this as a .BAT file and simply drop this in the top-level directory, together with the data file that contains the old names and new names of the files. And so, a double-click of "RRename.bat" will parse the content of "Filenames.txt" and work its way through all subfolders, renaming wherever matches are encountered. Boom.
To that end:
1. How do I make it so {SET "sourcedir=} indicates the current directory (i.e. the directory in which the batch file is located)? This way I wouldn't ever need to change this variable. (I should note that I am running this script on a network location, which requires me to map the drive, resulting in a different drive letter every time.)
2. How do I hard-code the name of the data file into the script itself? My goal is an easily replicated process minimizing user input (save for the content of the data file).
3. How do I stop the individual command windows from appearing? I'll be renaming thousands of files at a time and don't want to see thousands fo corresponding command windows.
Thank you!
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
:: read parameters
SET "filename1=%~1"
SET "filename2=%~2"
IF DEFINED filename2 GOTO name
IF NOT DEFINED filename1 GOTO :EOF
:: 1 parameter - must be filename
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO START /min "ren %%a" "%~f0" %%a
GOTO :eof
:: we have 2 parameters so rename pattern 1 to pattern 2
:name
FOR /r "%sourcedir%" %%a IN ("%filename1%*") DO CALL :process "%%a"
PAUSE
GOTO :EOF
:: Process the filenames and actually do the rename
:process
:: Name of file to be changed - name and extension of %1
SET "changeme=%~nx1"
:: REPLACE up-to-from-pattern with nothing = remainder of name/extension
CALL SET "endpart=%%changeme:*%filename1%=%%"
:: and RENAME...
ECHO(REN "%~1" "%filename2%%endpart%"
GOTO :eof
You would need to change the setting of sourcedir to suit your circumstances.
Revised data file
STWP01_00669087 BCBSRI-01849351
BCBSRI-01849357 2011-12-19_BCBSRI-01849357
STWP01_00669094 BCBSRI-01849369
Aimed at processing the above file, renaming files starting (column1 entries) to start (column2 entries.)
Method:
Run the batch as
batchname filename
This will execute the batch, processing filename
How:
having set the directory name to start processing from, set filename1&2 to the values of the parameters supplied.
If only 1 is supplied, it is the filename, so process it line-by-line and START a new process /min minimised "with the window name in the first set of quotes" and execute this same batch with the data from each line of the file in turn, then finish by going to :eof (end-of-file - built-in to CMD)
The sub-processes all have 2 parameters (eg BCBSRI-01849357 2011-12-19_BCBSRI-01849357) so processing passes to :name. This runs a for /r loop, from the specified source directory, with the name specified from the first column+* and executes :process passing the filenames found as parameter 1.
:process sets changeme to the filename in question, calculates endpart by removing the string filename1 from changeme which will deliver the er, end part.
Then simply rename the supplied filename to the replacement name+that endpart calculated.
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(REN to REN to actually rename the files.
The PAUSE is just to allow the proposed changes to be seen. Once the process has been verified, change the PAUSE to EXIT.
AAMOI, running
*batchname* STWP01_00669094 BCBSRI-01849369
for instance, would execute the recursive-rename from STWP01_00669094* to BCBSRI-01849369*
Sadly, "No luck" is meaningless.
I have made a minor, but significant change to the instructions. The PAUSE should be changed to an EXIT after testing.
After testing, the ECHO(... line should become
REN "%~1" "%filename2%%endpart%"
which actually executes the rename. If you've just deleted the line, it would explain the no-visible-result.
Having restored the original code and verified against a small representative dummy subtree, change the echo(... line and test again. The filenames should change. If not, something is dreadfully wrong. Needless to say, this works perfectly happily for me...
Then try again with the PAUSE changed to EXIT. This time, the windows generated will appear on the taskbar and then disappear when the rename for that line of the input file has finished. This will happen once for BCBSRI-01849357 rentwo for instance - not once for each individual file rename occurring.
To hard-code the filename, remove the line
IF NOT DEFINED filename1 GOTO :EOF
and replace
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO START /min "ren %%a" "%~f0" %%a
with
FOR /f "usebackqdelims=" %%a IN ("YOURFILENAMEHERE") DO START /min "ren %%a" "%~f0" %%a
For the "run from here" command, change
SET "sourcedir=U:\sourcedir"
to
SET "sourcedir=."
. means "the current directory"
If you place thisbatchfilename.bat into any directory on your PATH then you can run the routine simply by executing thisbatchfilename.
You can display your path by typing
path
at the prompt. PATH is the sequence of directories searched by windows to find an executable if it isn't found in the current directory. To chane path, google "change path windows" - experienced batchers create a separate directory on the path for batch files. Sometimes, they name the directory "Belfry".
I have a set of folders already named mm-dd-yyyy (for example 01-01-2014) but they will be more useful named yyyy-mm-dd (for example 2014-01-01). Using dos, how can I rename the folders switching the date parts around?
Assuming that you're talking about cmd.exe rather than the ancient MS-DOS command.com, you can do this reasonably easily(1).
The idea is to iterate over all directories in the current directory, using for /d. Then, for each one that matches a specific pattern (99-99-9999), you can use string manipulation to construct a rename command.
The checking for a correct format can be done with the regular expression capability of findstr.
#echo off
#setlocal enableextensions enabledelayedexpansion
rem Process every file. For each file with a valid format,
rem construct a rename command.
for /d %%a in (*) do (
set full=%%a
call :isvalidfmt !full!
if !res!==true (
set d2=!full:~0,2!
set m2=!full:~3,2!
set y4=!full:~6!
echo ren !full! !y4!-!m2!-!d2!
)
)
endlocal
goto :eof
rem Use findstr regex option to see if file name is correct format.
:isvalidfmt
set res=true
echo %1|findstr /r "^[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$" >nul:
if errorlevel 1 set res=false
goto :eof
Note that the script above (let's call it rengen.cmd) simply outputs the rename commands, it does not actually rename the files. That's good practice so you can see what it's going to do before you destroy your directories :-)
To actually rename the files (once you've confirmed it's safe), simply capture the output to another file then run that:
rengen >nextren.cmd
nextren
(1) If you are talking about command.com, I can't help you out there. The command interpreter has come a long way since those bad old days and the one that came with MS-DOS is seriously under-powered.
use dir and export to a file. Take it to Excel and create two columns, one with current name and one with new name and then bring it back to notepad and add RENAME command to each row as a prefix.
RENAME cuurentfilename newfilename is the command syntax.
I have to run a tool(.exe) that is stored in a particular folder.(Say C:\Temp)
The input parameter for this tool is the (.inf) files placed in various other folders/subfolders.(Say C:\Test\SampleInfFiles, C:\Test\SampleInfFiles\Inf2)
I want to create a batch file where i can run this tool recursively on the various folders.
I am not sure how to provide the folder name of the inf as the input parameter to the tool.
#echo off
for /r /d C:\Test\SampleInfFiles %%x in (dir /b *.inf) do(
pushd "%%x"
call C:\Test\ScanInf.exe
popd
)
I am new to all this. Could you please help create a batch file.
If I understand correctly, you need to specify the folder that contains one or more inf files to the executable, and not the inf files itself.
Apparently the order of parameters is important. for expects the part after /r to be a path. Furthermore, you can just specify * as a set.
The loop now browses all subfolders of the given folder. Inside the loop, it will check if that folder contains an inf file (on that level). If it does, the executable is called with the folder as parameter. Notice the use of ~ in the variable. This strips off any quotes, so you can safely add quotes without risking to have double quotes.
#echo off
for /d /r C:\Test\SampleInfFiles\ %%x in (*) do (
pushd "%%~x"
if exist %%x\*.inf call C:\Test\ScanInf.exe "%%~x"
popd
)
See: Using batch parameters
Here as a nice one-liner:
for /R "C:\Test\SampleInfFiles" /D %%X in (*.*) do if exist "%%~fX\*.inf" call C:\Test\ScanInf.exe "%%~fX"
If you want to run that in the command prompt directly, replace each %% by %.
I think the call command could be omitted.
I am very new to coding and bulk processes but i am looking for a command line SPECIFICALLY for windows command prompt and i am wondering if such a thing exists. So I have a folder containing 111 subfolders, with each subfolder containing between 20 and 40 png image files. Each subfolder is named 001-111 accordingly and the png files are ordered how i want them, however i am looking for a command line that would be able to quickly and efficiently name all the pngs in the folders to the name of the folder followed by the png number in brackets
e.g. for folder 037, i would want the png's to be renamed to: 037(1), 037(2), 037(3) etc...
I am hoping for the best although i am unsure such a code may not be possible or be simply done.
Also if you come up with a code that achieves this process, it would be great if you could reply with the simple command line that i could use rather than a full explanation because i am new to coding and far from fluent with the language or terms or how things work. I know this same process can be achieved by going select all>rename (ctrl a>f2) and renaming to the folder name however i need to use this process frequently and dont want to have to open each folder, i would rather have a command line for cmd that would do it swiftly
Thank you and a simple answer would be greatly appreciated
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "parentdir=u:\parent"
FOR /l %%a IN (1001,1,1111) DO (
SET dir=%%a&SET "dir=!dir:~1!"
FOR /f "delims=" %%i IN ('dir /a-d /b "%parentdir%\!dir!\*.png" 2^>nul') DO (
ECHO REN "%parentdir%\!dir!\%%~nxi" "!dir!(%%~ni)%%~xi"
)
)
GOTO :EOF
Test results:
Starting directory :
u:\parent\001\1.png
u:\parent\037\1.png
u:\parent\037\2.png
u:\parent\111\999 with spaces in name.png
Script response
REN "u:\parent\001\1.png" "001(1).png"
REN "u:\parent\037\1.png" "037(1).png"
REN "u:\parent\037\2.png" "037(2).png"
REN "u:\parent\111\999 with spaces in name.png" "111(999 with spaces in name).png"
Obviously, you'd need to replace the value assigned to parentdir with your actual target directory name.
The script will report the renames it proposes to do. To actually invoke the rename remove the ECHO keyword.
I would create a batch file like so:
renamepng.bat:
cd %%1
if ERRORLEVEL 1 goto end
for %f in *.png do mv "%f" "%%1(%f).png"
cd ..
:end
This will attempt to cd to the directory name provided on the command line, abort if that fails, then rename all the .png files and return to the previous directory
then call it like so:
for %d in ??? do call renamepng.bat %d
which will loop through all 3-character file and directory names in the current directory, can call the batch file on each one. Using call instead of just the batch file name causes execution to return to the loop when the batch finishes.