How can I move files based on their name? - batch-file

I'm trying to move files into existing sub-folders based on the file names.
For example, I want to move a file named AP16742 found in the directory X:\Files into a folder named AP in the directory X:\Files\AP. Other files named MO14823 I want to move into a folder named MO in the directory X:\Files\MO.
I'm inexperienced in coding, so I need explanations to go with a provided example.
This is what I tried:
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%*.xml" ') DO (
FOR /f "tokens=1delims=_-" %%b IN ("%%a") DO (
FOR /f "delims=" %%d IN ( 'dir /b /ad "%destdir%*%%b*" ' ) DO (
ECHO(MOVE "%%a" "%destdir%\%%d\"
)
)
)
GOTO :EOF

A simple explanation would have been:
you want to distribute files in X:\Files to subfolders with the
first 2 letters of the file name.
To get a substring you need to set the content from for variable into
a normal variable.
Setting and using a variable inside a (code block) requires delayed
expansion.
#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
Pushd "X:\Files"
For %%A in (*) do (
Set "File=%%~nA"
if not exist "!File:~0,2!" md "!File:~0,2!" 2>&1>Nul
Move "%%A" "!File:~0,2!"
)
Popd
In case you want to move only distinct 2 letter pairs and not all files that's also possible without great effort.

A modification of LotPings answer, this uses RoboCopy with its /MOV option, which will create directories as needed and move the files to them:
#Echo Off & SetLocal EnableDelayedExpansion
CD /D "X:\Files" 2>Nul || Exit /B
For %%A In (*) Do (Set "File=%%~nA"
RoboCopy . "!File:~,2!" "%%A" /MOV >Nul)

Related

batch script how to create a string out of different variable parts

in my company we create software for different customers to handle our machines. As each product is unique, so is the control software, but not completely new. So for a start we copy an old project, rename it and change it until it fits.
Usually the directory name is the name for the new program (our ide uses the directory name, but also relies on some other files following the same name scheme).
For the renaming I've wrote a short batch script which finds the old name scheme and retrieves from the directory name the new one.
But the only solution I've found for this uses a new batchfile for each file to be renamed.
Is there a better way to get the content of !progNeu! ?
#echo off
SETLOCAL enabledelayedexpansion
set pfad=%CD%
for /d %%A in (%pfad%) do (set progNeu=%%~nxA)
for /f "tokens=1,2 delims=|" %%B in ('dir /b *.s19 ^| findstr /v "appl"') > do (
set progAlt=%%B
set rumpfAlt=!progAlt:.s19=!
>x ECHO !rumpfAlt!&FOR %%C IN (x) DO SET /A strlength=%%~zC - 2&del x
for %%D in (!rumpfAlt!*.*) do (
set progAlt=%%D
>x.bat echo #echo off
>>x.bat echo set ausg=!progAlt!
>>x.bat echo echo %%ausg:~!strlength!%%
for /f "" %%E in ('x.bat') do (
set "dateiNeu=!progNeu!%%E"
if exist !dateiNeu! del !dateiNeu!
rename %%D !dateiNeu!
)
del x.bat
)
)
If I have not missed something, this could be the equivalent to your code
#echo off
setlocal enableextensions disabledelayedexpansion
set "pfad=%CD%"
for /d %%A in ("%pfad%") do (
for /f "delims=" %%B in ('
dir /b *.s19 ^| findstr /v "appl"
') do for %%D in ("%%~nB*.*") do (
set "progAlt=%%D"
setlocal enabledelayedexpansion
for %%E in ("!progAlt:%%~nB=!") do (
endlocal
echo move /y "%%D" "%%~nxA%%~E"
)
)
)
I have removed almost all the inner variables that are simply using the values that the for replaceable parameters already hold, and used the adecuated modifiers to retrieve the needed part from the file names.

moving files to folders based on extension

Finally I got to move files with different extensions into folders according to their extensions, but I cannot get rid of the "." preceding the created folders... Here's my batch file:
for %%i in (*) do mkdir "%%~xi" & move "%%i" "%%~xi"
Please help me remove the dot. Thanks
One way:
setlocal enabledelayedexpansion
for %%i in (*) do (
set ext=%%~xi
set ext=!ext:~1!
mkdir "!ext!"
move "%%i" "!ext!"
)
What you are doing is just creating a folder names after the file extension. To remove the dot all you need to do is remove the first character.
setlocal enabledelayedexpansion
for %%i in (*) do (
set "x=%%~xi"
set x=!x:~1,400!
mkdir "!x!"
move "%%i" "!x!"
)
pause `
If you by chance just want to rename the folders:
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%D in ('dir /a:d /b') do (
set x=%%D
set x=!x:~1,100!
set y=!x:~0,1!
if "!y!"=="." (
rename "%%D" "!x!"
)
)
pause

Delete all files except filenames with specific string

I have 1000's of files like TOP_QUERIES-abc.com.au.csv,TOP_QUERIES-www.abc.com.au.csv, TOP_QUERIES-m.lmn.com.au.csv, TOP_QUERIES-blog.com.au.csvand get-files.php
Is it possible to delete all the .csv files from a folder except for files starting with blog. ,m. , www, and .php from the folder?
I know its possible in php but how can I achieve in batch file?
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
SET "exclude=blog. m. www."
FOR /f "delims=" %%a IN (
'dir /b /a-d "%targetdir%\*.csv" '
) DO (
ECHO %%a | findstr /B /L "%exclude%" >NUL
IF ERRORLEVEL 1 ECHO(DEL "%targetdir%\%%a"
)
GOTO :EOF
This should get the task done for you. You would need to change the setting of targetdir to suit your circumstances.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(DEL to DEL to actually delete the files.
The .php files are excluded because they don't match the *.csv filename - or did you want to not-delete files starting .php? If so, simply add .php into the exclude variable...
Revision for efficiency:
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
SET "exclude=blog. m. www."
FOR /f "delims=" %%a IN (
'dir /b /a-d "%targetdir%\*.csv" ^| findstr /B /L "%exclude%"'
) DO (ECHO(DEL "%targetdir%\%%a"
)
GOTO :EOF

create folders based on string in file name

I need a batch file to create a process for a list of files in a directory.
The filename structure is, for example: 00000_AAA_132144_2012021.txt
I need the batch to:
1 - Create a folder name based on the numbers after the second underscore, as this is the only constant in the naming.
2 - Move the file into the new folder.
In the example of the above the batch would create a folder called 132144 and then move the file 00000_AAA_132144_2012021.txt into the folder
For a similar requirement I used the script Endoro created for me (below). Is it possible to modify this to meet my requirement?
#echo off &setlocal
for /f "delims=" %%i in ('dir /b /a-d *.PDF') do (
set "filename1=%%~i"
setlocal enabledelayedexpansion
set "folder1=!filename1:~11,6!"
mkdir "!folder1!" 2>nul
move "!filename1!" "!folder1!"
endlocal
)
If you know that the filenames will be the same length, you can do the following to get the numbers after the second underscore -
set filename=00000_AAA_132144_2012021.txt
set dirname=%filename:~10,6%
If the spacing may vary - you can do the following -
for /f "delims=_ tokens=3" %%a in ('echo %filename%') do set dirname=%%a
And yes, the script written for you seems to do essentially the same thing as what you're asking - I've edited it to do what you've asked -
#echo off
setlocal enabledelayedexpansion
for /f %%i in ('dir /b /a-d *.txt') do (
set "filename=%%~i"
for /f "delims=_ tokens=3" %%a in ('echo !filename!') do set folder=%%a
mkdir "!folder!" 2>nul
move "!filename!" "!folder!"
)
This will move all *.txt documents to a folder created based on the third section of the text files name. Note that this will cause problems if you have .txt documents in the directory that do not follow the same naming standard.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\sourcedir"
SET "destdir=c:\destdir"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%\*_*_*_*.txt" ') DO (
FOR /f "tokens=3delims=_" %%m IN ("%%a") DO (
ECHO MD "%destdir%\%%m"
ECHO MOVE "%sourcedir%\%%a" "%destdir%\%%m\"
)
)
GOTO :EOF
Endoro's routine selects .pdf files, you've specified .txt
Find filenames matching the mask, find the third _-separated token in the name, make that directory and then move the file.
The required commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO MD to MD to actually create the directories and change ECHO MOVE to MOVE to actually move the files.
Append 2>nul to suppress error messages (eg. when the directory already exists)
Append >nul to suppress report messages (eg. 1 file moved)

Create folder based on group of files

I have files with varying names...
Tim-01.jpg
Tim-02.jpg
Tim-03.jpg
jack-01.jpg
jack-02.jpg
jack-03.jpg etc in a single folder
I want to move all tim files into Tim folder and jack files to Jack folder etc.
Can it be done using .bat files ? If yes, please share the code for it.
Thank You.
#echo off
setlocal
set sourcedir=c:\sourcedir
for /f "tokens=1*delims=-" %%a in ('dir /b /a-d "%sourcedir%\*-*.*") do (
md "%sourcedir%\%%a" 2>nul
echo move "%sourcedir\%%a-%%b" "%sourcedir%\%%a\"
)
Note that the 2>nul suppresses error messages created when an attempt is made to recreate an existing directory
The MOVE is merely ECHOed. Remove the ECHO keyword to activae the move. It may also be prudent to append >nul to the MOVE statement to suppress the "1 file(s) moved" message.
As you may know, there are no arrays in Batch. So let's just use one.
#ECHO OFF &SETLOCAL
for /f "tokens=1*delims=-" %%a in ('dir /b /a-d *-*.jpg') do set "$%%a=%%a"
for /f "tokens=1*delims==" %%a in ('set $') do robocopy "%cd%" "%cd%\%%b" "%%b*" /mov /l
Remove /l from robocopy to make it working.
EDIT - Changed code to reduce the number of file moves. Now, all files with the same prefix get moved in one command.
#echo off
setlocal enableextensions
rem source of images
set "_dir=."
rem for each jpg with a dash in its name
for %%f in ("%_dir%\*-*.jpg") do (
rem if the file still exists (maybe it has been moved)
rem then split the file name with the dash as delimiter
if exist "%%~ff" for /F "tokens=1 delims=-" %%s in ("%%~nf") do (
rem and if we get a folder target, move the all the files
rem with same prefix to proper folder
if not "%%~s"=="" (
robocopy "%_dir%" "%_dir%\%%~s" "%%~s-*.jpg" /mov /njs /njh
)
)
)
endlocal
EDIT2 - Changed to adapt to comments
#echo off
setlocal enableextensions enabledelayedexpansion
rem source of images
set "_dir=."
rem for each jpg with a dash in its name
for %%f in ("%_dir%\*-??.jpg") do (
rem if the file still exists (maybe it has been moved)
if exist "%%~ff" (
rem get the filename without the 3 last characters
set "_target=%%~nf"
set "_target=!_target:~0,-3!"
rem and if we get a folder target, move the all the files
rem with same prefix to proper folder
if not "!_target!"=="" (
robocopy "%_dir%" "%_dir%\!_target!" "!_target!-??.jpg" /mov /njs /njh
)
)
)
endlocal

Resources