remove string from filenames with .bat batch file - regex

I have a folder with thousands of filenames like this. I need to put them inside folders and remove the useless parts from the filenames. I need to do this before adding the files inside my XBMC library.
[ www.AnnoyingSpam.com ] Some.File.Name.With.A.Very.Long.String.avi
[ www.AnnoyingSpam.com ] Another.File.With.A.Very.Long.String.mpg
[ www.AnnoyingSpam.com ] Again.And.Again.mp4
First, I want to strip the AnnoyingSpam.com tags in the files
Then, create a folder based on the file name without the tag and without the extension
Finally, move the file to the new folder
Repeat for the rest of the files in the root directory of the batch file
So far all I got is a script that will create folder and move files. But it adds the tag "Folder" to each folder and it doesn't remove the AnnoyingSpam.com tag
#echo off
for /f "usebackq delims=?" %%a in (`dir /a-d /b`) do (
if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a"
)
goto :EOF
:func
set file=%~1
set dir=%file% Folder
md "%dir%" Folder 2>nul
move "%file%" "%dir%"
goto :EOF
So my question is how can i remove these strings from the folder names that are being created in the above script:
"[ www.AnnoyingSpam.com ]"
" Folder"

Since you are performing the check if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a", my understanding is that you will be running the batch from inside the 'target' folder.
What follows is a batch script, based structurally on your sample, that accomplishes the necessary filtering and handles the rename and move operations.
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "usebackq delims=?" %%a in (`dir /a-d /b`) do (
if not "%%~dpnxa"=="%~dpnx0" call :func "%%~a"
)
endlocal
echo Done.
goto EOF
:func
set file=%~1
for /F "delims=" %%a in ("!file!") do (
rem stripped extension, next step is to filter to remove the 'spam' part
set "c=%%~Na"
rem original filename, will be needed for the renaming
set "o=%%~a"
rem store the extension to use later on when re-constructing the filename
set "e=%%~xa"
rem this is effectively a multichar stripper; filters the 'spam' part out
set "c=!c:[ www.AnnoyingSpam.com ] =!"
rem reconstruct the filename
set "f=!c!!e!"
rem echo !o! : !c! : !e! ::: !f!
rem rename original file to the filtered version
ren "!o!" "!f!"
rem create dir named after the filtered filename, if it does not already exist; just a precaution
if not exist !c! (md !c!)
rem move the filtered file to the appropriate dir
move "!f!" "!c!" > nul
)
:EOF
The script is almost self-explanatory (see the comments inside), however there are some aspects that I would like to point out:
The instructions setlocal ENABLEDELAYEDEXPANSION and endlocal, that in fact form a wrap around the for-loop, establish that the variables inside the loop will be evaluated (expanded) at the execution time and not during parse time. Notice that the variables are referenced inside the loop as !var!. See more on this here.
The removal of the unwanted 'spam' part is performed by this command: set "c=!c:[ www.AnnoyingSpam.com ] =!". What it does is best described by the following example: set "var=!var:substring1=substring2!", has as a result the substitution of every occurrence of substring1 by substring2 in var.
If substring2 is null (as is the case here), then the actual effect is the removal of every substring1 pattern found in the original variable. More on this here, and for an interesting use as a multichar delimiter see dbenham's answer here.
And, as always, test thoroughly before you use the script on the actual folders.

I know you've asked for a batch script, but if you have php installed, you can use this:
renameSpam.php
<?php
$removeTag = "[ www.AnnoyingSpam.com ]";
foreach(glob("*.*") as $file){
if (strpos($file, $removeTag) !== false) {
$newFile = trim(str_ireplace($removeTag, "", $file));
$ext = pathinfo($newFile, PATHINFO_EXTENSION);
$fnNoExt = basename($newFile,".".$ext);
if(!is_dir($fnNoExt)){
mkdir($fnNoExt, 0777);
rename($file, "./$fnNoExt/$newFile");
}else{
rename($file, "./$fnNoExt/$newFile");
}
}
}
Place renameSpam.php on the directory with the files to rename and execute as php renameSpam.php.
I've tested this on windows and linux and it works as intended.

Related

Find and remove remote hidden file

I'm trying to create a small script that looks for a specific file in an hidden folder and remove it using IF ELSE, but it doesn't seem to work. It works when I try to find and delete a local file, but not when I try a remote hidden file.
This is my code:
#echo off
set /p destination="Enter destination PC name: "
#echo off
set /p username="username: "
echo.
echo [33m'Removing 'notes.ini' file[0m
timeout /T 2 /NOBREAK > nul
echo.
if exist "\\%destination%\C$\Users\%username%\AppData\Local\Lotus\Data\notes.ini" (
del /A /Q /F "\\%destination%\C$\Users\%username%\AppData\Local\Lotus\Data\notes.ini"
echo [92m'Notes.ini' cleared.[0m
) else (
echo [33m'Notes.ini' doesn't exist.[0m
)
echo.
timeout /T 2 /NOBREAK > nul
echo [92mScript clompleted[0m
I tried with a local file, and then the scripts works, but not with a remote hidden file. I always get the "else" statement as return with hidden files

URL with operators (=, -) not working within if-statement

I'm having an issue with an URL in an if-statement using batch.
#ECHO OFF
SET /P input="Insert Link "
if %input%==l (echo true) else (echo false)
cmd /k
I want to determine if the user input is a link or a single character (in this case l). I get that the operators within the URL might cause the problem. But shouldn't the if-statement just check if %input% is l and everything else would trigger the else? Using SET %input%=l leads to the true case being triggered.
Any ideas on how to make this work in a simple way? Am I missing something regarding syntax?
Putting %input% and l within the if-statement in quotes solved the problem.
#ECHO OFF
SET /P input="Insert Link "
if "%input%"=="l" (echo true) else echo false
cmd /k
The way the Command Line works, %ThisIsAVariable% will be replaced with whatever ThisIsAVariable contains and then be interpreted as such. Hence, running your example prompts the following error:
=6zswl5YrvVw==l was unexpected at this time.
The simplest way to solve this is to wrap your %input% with ""
e.g.
#ECHO OFF
SET input=https://www.youtube.com/watch?v=6zswl5YrvVw
if "%input%"==l (echo true) else (echo false)
cmd /k
That would prompt false

IF NOT EXIST not working in Windows Batch

I am trying to insert an "if not exist" in a windows batch file where another similar IF with the same formatting IS working - can't tell why this one fails after researching and testing.
The second If not exist working as expected When the first is REMd out
Formatting is the same, %INIFile% is defined
#echo off
setlocal EnableExtensions Enabledelayedexpansion
set "TODAY=%Date:~4,2%-%Date:~7,2%-%Date:~12,2%"
set "NOW=%time:~0,2%.%time:~3,2%.%time:~6,2%"
set "TempFile=%TEMP%\%~n0.tmp"
set "INIFile=Parameters_INI.ini"
if not exist ".\%INIFile%" (
echo ERROR: List file "%INIFile%" not found.
echo ERROR: List file "%INIFile%" not found.>>%LogFile%
goto :EndBatch
)
:: Get Parameters
call :get-ini %INIFile% Parameters ListFile result
Set "ListFile=%result%"
call :get-ini %INIFile% Output LogName result
Set "LogFile=%result%_%EntryName%_%TODAY%_T%NOW%_Log.txt"
Echo INI File Updater
Echo PC List: %ListFile%
Echo PC List: %ListFile%>>%LogFile%
if not exist ".\%ListFile%" (
echo ERROR: List file "%ListFile%" not found.
echo ERROR: List file "%ListFile%" not found.>>%LogFile%
goto :EndBatch
)
goto :EndBatch
:get-ini <filename> <section> <key> <result>
set %~4=
set insection=
for /f "usebackq eol=; tokens=*" %%a in ("%~1") do (
set line=%%a
if defined insection (
for /f "tokens=1,* delims==" %%b in ("!line!") do (
if /i "%%b"=="%3" (
endlocal
set %~4=%%c
goto :eof
)
)
)
if "!line:~0,1!"=="[" (
for /f "delims=[]" %%b in ("!line!") do (
if /i "%%b"=="%2" (
set insection=1
) else (
endlocal
if defined insection goto :eof
)
)
)
)
:EndBatch
endlocal
pause
Parameters_INI.ini
[Parameters]
ListFile=PCList.txt
Target=SMSStart.ini
TarDIR=Storeman
SectionName=[Maintenance]
EntryName=Reboot
NewValue=1
[Output]
LogName=INI_Update
PCList.txt
LAB-LANE005
LAB-LANE006
LAB-LANE001
LAB-LANE007
LAB-LANE008
echo ERROR: List file "%ListFile%" not found.>>%LogFile%
You don't appear to have ever set LogFile to a value, so if it's not set, this line will fail when it's parsed as >> on it's own at the end of the line is invalid syntax, even if it's not run.
If you set LogFile before the batch file, or in the first lines of your batch file, the rest should work.

Add a line in XML using batch file before a tag [duplicate]

This question already has answers here:
Changing tag data in an XML file using windows batch file
(3 answers)
Closed 6 years ago.
I have an XML file of the type
....
<sometag>
<tag attr_name1="long filename1" />
<tag attr_name2="long filename2" />
....
</sometag>
....
Before </sometag> I want to add <tag attr_name="long filename" /> so far the code in my Batch Script for Windows is:
#echo off
setlocal enableDelayedExpansion
set "newValue=^<tag attr_name="long filename" /^>
set newline=^& echo.
type "File.xml"|replace "(</tag>)" "!newValue!$1" >dupFile.xml
move /y "dupFile.xml" "File.xml"
I get "Path not found - </tag>" and File.xml contains "No Files Replaced". I know its not best practice to edit XML from batch file but can't use third party executables unfortunately. Can someone please help with where I'm going wrong?
Also I've checked the thread about changing data between tags in XML using batch file, when I use the suggested code there and alter to my requirement i get the above error.
If </sometag> appears only once in your XML and if it won't screw up the hierarchy inserting your new <tag> node on the line before, you could just loop through your XML file with a for /F loop, checking whether each line contains </sometag>. When found, simply echo your new <tag> prior to echoing the matched line.
#echo off
setlocal
>"newfile.xml" (
for /f "usebackq delims=" %%I in ("xmlfile.xml") do (
set "line=%%I"
setlocal enabledelayedexpansion
if not "!line!"=="!line:/sometag=!" (
echo ^<tag attr_name="long filename" /^>
)
endlocal
echo(%%I
)
)
type "newfile.xml"
But really, assuming your XML is fully valid, the most elegant solution is to parse the XML as structured data, rather than as complicated text to hack and scrape. That way it doesn't matter whether your code is beautified, minified, uglified, or whatever. The parser still understands it, regardless of indentation and line breaks. You can do this with languages already built into Windows -- VBScript, JScript, PowerShell, C#, and the list goes on. Batch might be the only language with which you're familiar, but it isn't the only language available in a base install of Windows. Here's a quick and dirty batch + PowerShell hybrid script to demonstrate. (Save it with a .bat extension.)
<# : batch portion (within a multiline PowerShell comment)
#echo off & setlocal
set "infile=test.xml"
set "parentNode=sometag"
set "newTag=tag"
set "newAttr=attr_name"
set "attrVal=long filename"
set "outfile=new.xml"
powershell -noprofile -noninteractive "iex (${%~f0} | out-string)"
type "%outfile%"
goto :EOF
: end batch (multiline comment) / begin PowerShell hybrid code #>
[xml]$xml = gc $env:infile
$parent = $xml.documentElement.selectSingleNode("//$env:parentNode")
$new = $xml.createElement($env:newTag)
[void]$new.setAttribute($env:newAttr, $env:attrVal)
[void]$parent.appendChild($new)
$xml.save($env:outfile)

Nested If Exist statements in Batch File

Ok, I'm trying to do a couple nested IF EXIST statements to check for the presense of a couple folders. If the first folder exists, set Folder1 to equal 1, and then skip to Install. Same with the Folder2, and then if neither folder exists just skip to install.
But even when Folder1 doesn't exist, this still sets %Folder1% to equal 1. What am I missing/not doing?
Thanks!
if exist "c:\folder1" set Folder1=1
echo %Folder1%
goto install
else if exist "c:\folder2" set Folder2=1
echo %Folder2%
goto Install
else goto Install
:Install
Two fundamental problems:
A compound statement must be parenthesised.
Within parentheses, changing a variable value will NOT be visible UNLESS you have executed a SETLOCAL ENABLEDELAYEDEXPANSION - and even then you'd need to use !var! not %var%
So:
SETLOCAL ENABLEDELAYEDEXPANSION
if exist "c:\folder1" (
set Folder1=1
echo !Folder1!
goto install
) else if exist "c:\folder2" (
set Folder2=1
echo !Folder2!
goto Install
) else goto Install
:Install
Or preferably,
#ECHO off
if exist "c:\folder1" (
set Folder1=1
goto install
) else if exist "c:\folder2" (
set Folder2=1
goto Install
) else goto Install
:Install
SET folder
Or even simpler
#ECHO off
if exist "c:\folder1" set Folder1=1&goto install
if exist "c:\folder2" set Folder2=1&goto Install
:Install
SET folder
Test:
#ECHO OFF
setlocal
SET "folder1="
SET "folder2="
ECHO.----------No folders
DIR /b /ad c:\folder*
CALL :test
ECHO.----------Folder 1 only
MD c:\folder1
DIR /b /ad c:\folder*
CALL :test
ECHO.----------Folder 2 only
RD c:\folder1
MD c:\folder2
DIR /b /ad c:\folder*
CALL :test
ECHO.----------Both
MD c:\folder1
DIR /b /ad c:\folder*
CALL :test
RD c:\folder1
RD c:\folder2
GOTO :eof
:test
if exist "c:\folder1" set Folder1=1&goto install
if exist "c:\folder2" set Folder2=1&goto Install
:Install
SET folder
SET "folder1="
SET "folder2="
GOTO :eof
This test creates and deletes the two directories in question.
Here's the result:
----------No folders
----------Folder 1 only
folder1
Folder1=1
----------Folder 2 only
folder2
Folder2=1
----------Both
folder1
folder2
Folder1=1
Note that
SET "folder1="
SET "folder2="
Which is executed both at the start and after each report ensures that the environment variables in question are removed from the environment to prevent the code giving false results on stale information.
if exist "c:\folder1" (
set Folder1=1
echo %Folder1%
goto install
) if exist "c:\folder2" (
set Folder2=1
echo %Folder2%
goto Install
) else goto Install
:Install
This code doesn't set %folder1%=1 if folder1 doesn't exists, and it produces no output in this case. If Folder1 doesn't exists AND Folder2 exists THEN %folder2% is set to 1, otherwise %folder2% is empty. Put an unclosed left parentheses after the echocommand to suppress the output, if a variable is empty.
#echo off &setlocal
if exist "c:\folder1" set "Folder1=1"
echo(%Folder1%
if not defined Folder1 if exist "c:\folder2" set "Folder2=1"
echo(%Folder2%
goto Install
:Install
endlocal