Trying to create a script that will take the third token of a file name, create a folder based on it and move the associated file to that folder.
Have got this so far:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3,4 delims=" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%c
ECHO MOVE "%%a %%b %%c %%d" .\%%c\
)
POPD
GOTO :EOF
Only problem is the folder being created is including the file extension where as I just need the folder to be named the third token.
Example file name:
"File Number 10.pdf
Expected folder name:
10
Thanks
Why did you use delims=? This will remove delimiter, and take whole line to %%a.
Try this:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%~nc
ECHO MOVE "%%a %%b %%c" .\%%~nc\
)
POPD
GOTO :EOF
When no delims= set, it will use space. So %%c will be 10.pdf, ~n is to extract its name part.
This is based on your question, which you can concatenate %%a %%b %%c together with spaces, then it's simple.
If your filenames are more complicated, then an inner for loop is better.
-- Which another question already gave a great solution.
Here's an alternative, which will just use the last space delimited string/number, regardless of how many there are, (if there are none it will use the whole filename)!
#Echo Off
For %%A In ("D:\Sourcedir\*.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
And if you wanted to move only those which have at least one space, you can include that inside the For parentheses.
#Echo Off
For %%A In ("D:\Sourcedir\* *.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
You can run 2 for loops get the full name in the first, then split the name in the second loop, get the 3rd token, create the directory and then copy the actual file name from the first loop.
This way you do not need to try and patch the name together again, I know it works, but it is ugly and not prefered:
#echo off
setlocal enabledelayedexpansion
set "sourcedir=D:\Sourcedir"
pushd %sourcedir%
for %%a in (*.pdf) do (
set "var=%%a"
for /f "tokens=3" %%i in ("!var!") do (
echo md "%%~ni"
echo move "%%~a" "%%~ni"
)
)
popd
goto EOF
For more information on these commands, see help for each from cmd.exe i.e
for /?
set /?
setlocal /?
set and setlocal has very specific information regarding delayed expansion.
Related
I'm looking to make a BATCH file in order move thousands of files into a NEW folder with the name based on the first word of the name.
example:
c:\Monkeys likes apples.jpg
c:\Monkeys likes bananas.jpg
c:\Elephants likes avocados.jpg
c:\Elephants likes Grapefruit.jpg
-->
C:\Monkeys\Monkeys likes apples.jpg
C:\Monkeys\Monkeys likes bananas.jpg
C:\Elephants\Elephants likes avocados.jpg
C:\Elephants\Elephants likes Grapefruit.jpg
The results should show a folder called 'Monkeys' and 'Elephants' with the files inside it.
This is what i used, although this isn't selecting the first word only properly.
#echo off
setlocal enabledelayedexpansion
set folderpath=G:\Emulator\GAMES\test\
for %%f in (%folderpath%\*.*) do (
set "foldername=%%~nf"
md "!foldername:~0,-3!" >nul 2>&1
move "%%f" "!foldername:~0,-3!"
)
thanks in advance!
#echo off
setlocal enabledelayedexpansion
set "folderpath=G:\Emulator\GAMES\test\"
Pushd "%folderpath%"
For %%A in (*.jpg) do For /f %%B in ("%%~nA") Do (
if not exist %%B md %%B >nul 2>&1
Echo move "%%~fA" %%B
move "%%~fA" %%B
)
Popd
Here's an alternative method, how does it perform?
#Echo Off
Set "folderpath=G:\Emulator\GAMES\test"
For %%A In ("%folderpath%\* *.*") Do Call :Sub "%%A"
Timeout -1
Exit/B
:Sub
Set "newfolder=%~n1"
Set "newfolder=%newfolder: ="&:%"
If Not Exist "%~dp1%newfolder%\" MD "%~dp1%newfolder%"
Move %1 "%~dp1%newfolder%"
The above code looks specifically for filenames containing at least one space, if you wish to include every file, change "%folderpath%\* *.*" to "%folderpath%\*.*" on line 4.
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.
I have created a batch file in a windows server to parse the name of the files stored in a folder.
The name of the file contains a set of parameters splitted by the hyphen, e.g.
ACC-INV-APR-2015
I need to check the syntax correctness of the first two parameters (department and document type) e.g. I would avoid that the hyphen is inserted more than a time in the file name.
On the basis of the check, the files with wrong syntax will be moved to a folder.
We have to consider that, apart the first two parameters that are mandatory, the other ones could be skipped and therefore the file name could have some repetitive hypens after the first two parameters, e.g.
FIN-DOC-APR-2015--MFH-P01
We would avoid to have some file name like: FIN--DOC-APR-2015-MFH-P01
I have created the following batch file but I don't know how to skip the filename with wrong syntax....
Thank you.
setlocal EnableDelayedExpansion
set source=\\fileserver\share$\archive
set dest_ok=\\fileserver\share$\fileok
set dest_not=\\fileserver\share$\error
FOR /R %source% %%f in (*.*) do call :Proc1 "%%f"
goto End
:Proc1
Set filename=%1%
For %%A in (%filename%) do (
Set Folder="%%~dpA"
Set Name=%%~nxA
)
for /f "tokens=1,2 delims=- " %%a in ("%Name%") do call :Proc2 %%a %%b
goto :eof
:Proc2
set department=%1
set typedoc=%2
FINDSTR /x "%department%" c:\0_scripts\arch\departments.txt
if %errorlevel%==0 FINDSTR /x "%typedoc%" c:\0_scripts\arch\typedocs.txt
if %errorlevel%==0 move /Y %filename% %dest_ok%
if %errorlevel%==1 move /Y %filename% %dest_not%
goto :eof
:End
Sounds like a job for regular expressions. The Windows utility findstr will let you match based on a regular expression. It exits status 0 if found, non-zero otherwise. This lends itself to conditional execution. In a cmd console, enter findstr /? for details on supported regexp syntax.
It'll also speed things up to cache the contents of departments.txt and typedocs.txt into variables, rather than open, read, close, repeat for each file checked.
So, with that in mind, here's how I'd do it:
#echo off
setlocal
set "source=\\fileserver\share$\archive"
set "dest_ok=\\fileserver\share$\fileok"
set "dest_not=\\fileserver\share$\error"
set "departments.txt=c:\0_scripts\arch\departments.txt"
set "typedocs.txt=c:\0_scripts\arch\typedocs.txt"
setlocal enabledelayedexpansion
for /f "usebackq delims=" %%I in ("%departments.txt%") do set "dept=%%~I;!dept!"
for /f "usebackq delims=" %%I in ("%typedocs.txt%") do set "type=%%~I;!type!"
endlocal & set "dept=%dept%" & set "type=%type%"
for /r "%source%" %%I in (*) do (
rem // Does filename match /^[a-z]+-[a-z]+/i ?
echo %%~nxI | findstr /i "^[a-z][a-z]*-[a-z][a-z]*" >NUL && (
rem // Yep. Check whether department and doc type is in allowed list.
for /f "tokens=1-2 delims=- " %%a in ("%%~nxI") do (
// if %dept% doesn't equal itself with %%~a removed, and so on...
setlocal enabledelayedexpansion
if not "%dept%"=="!dept:%%~a=!" if not "%type%"=="!type:%%~b=!" (
// All checks passed. Moved to OK folder.
move /y "%%~fI" "%dest_ok%"
)
endlocal
)
)
// If the file hasn't been moved by now, it must've failed a test.
if exist "%%~fI" move /y "%%~fI" "%dest_not%"
)
C:\0_scripts\arch>(
echo MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf | findstr /i "^[a-z][a-z]*-[a-z][a-z]*" 1>N
UL && (for /F "tokens=1-2 delims=- " %a in ("MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf") do (
setlocal enabledelayedexpansion
if not "TEF6;TEF10;QMM8;QMM73;QMM72;QMM71;QMM7;QMM6;QMM13;QMM1;QMM;MFP2;MFP1;MFH3;MFH2;MFH1;MFH ;MFG3;MFG22;MFG21;MFG2;
MFG11;MFG1;MFG;MFB;HSE;COS;" == "!dept:%~a=!" if not "WPL;WP;WBP;WB;WAL;WAG;WA;VTL;VTK;VDP;VBT;VBL;VB;VAW;VAP;VA;UVA;UMV
;TSS;TRN;TKU;TDC;SYM;SWD;SWC;SW;SVS;SVA;SV;STR;STL;STF;STB;SPC;SBT;SAM;RTZ;RTP;RPL;RP;RNO;RHW;RAW;QMP;QMA;QM;QBG;QB;QAM;
PZB;PUM;PRV;PRS;PRJ;PRA;PQP;PPM;PPK;PP;PNR;PLB;PH;PFH;PDV;PDR;PDC;PDB;PAP;PAL;PAG;OPS;OPL;OEE;NOR;NKA;MUB;MSZ;MON;MOD;MB
B;MNT;LZT;LZS;LZN;LPV;LPN;LPL;LPC;LPA;LHT;LDP;LBA;KSB;KPV;KPA;KOE;KOB;KBU;KBL;KB;IAM;HZG;HZ;HSE;HRB;HFG;HF;HE;HAZ;GMD;GE
Z;GBB;FVT;FRM;FPL;FPK;FPI;FPA;FP;FMP;FME;FMD;FMA;FLP;FLB;FIM;FHW;FGY;FGV;FGS;FGP;FGL;FGK;FGE;FGD;FGB;FGA;FDA;FA;EZZ;EWZ;
EWS;EVT;EV;ETZ;ETL;ESZ;EPB;EP;ECM;DVL;ECR;DV;DRX;DRW;DRV;DRQ;DRK;DRF;DMD;DIF;DLP;DER;DDI;DBL;DB;DAT;D01;CPC;CIP;CHL;CE;C
AP;BVT;BVS;BVB;BV;BUG;BSV;BST;BSS;BS;BPZ;BLD;BDL;BBL;BBD;BB;BAL;BAD;ANH;AGZ;AFK;AEN;AED;AAW;AA;" == "!type:%~b=!" (
move /y "\\server1\digit$\deposito\MFH3\MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf" "\\server1\digit$\errori"
pause
)
endlocal
) )
if exist "\\server1\digit$\deposito\MFH3\MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf" move
/y "\\server1\digit$\deposito\MFH3\MFH3-FHW-20150529-F001MD14895-20301231-V01-OP20-TRIFLEX-CP1_H--.pdf" "\\server11\digit$\ok"
pause
)
1 file(s) moved.
Press any key to continue . . .
Blockquote
I have changed the script and came back to your original version .
This is the output of the batch file when a file correct is processed:
if exist "\server1\digit$\deposito\MFH3\MFH3--FHW-20150512-F01MD14861-20301231-V02-OP20-TRIFLEX-CP1H--.pdf" move
/y "\server1\digit$\deposito\MFH3\MFH3--FHW-20150512-F01MD14861-20301231-V02-OP20-TRIFLEX-CP1H--.pdf" "\server1\
digit$\errori"
pause
)
1 file(s) moved.
Press any key to continue . . .
C:\0_scripts\arch>(
echo MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf | findstr /i "^[a-z][a-z]-[a-z][a-z]" 1>NU
L && (for /F "tokens=1-2 delims=- " %a in ("MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf") do (
setlocal enabledelayedexpansion
if not "TEF6;TEF10;QMM8;QMM73;QMM72;QMM71;QMM7;QMM6;QMM13;QMM1;QMM;MFP2;MFP1;MFH3;MFH2;MFH1;MFH ;MFG3;MFG22;MFG21;MFG2;
MFG11;MFG1;MFG;MFB;HSE;COS;" == "!dept:%~a=!" if not "WPL;WP;WBP;WB;WAL;WAG;WA;VTL;VTK;VDP;VBT;VBL;VB;VAW;VAP;VA;UVA;UMV
;TSS;TRN;TKU;TDC;SYM;SWD;SWC;SW;SVS;SVA;SV;STR;STL;STF;STB;SPC;SBT;SAM;RTZ;RTP;RPL;RP;RNO;RHW;RAW;QMP;QMA;QM;QBG;QB;QAM;
PZB;PUM;PRV;PRS;PRJ;PRA;PQP;PPM;PPK;PP;PNR;PLB;PH;PFH;PDV;PDR;PDC;PDB;PAP;PAL;PAG;OPS;OPL;OEE;NOR;NKA;MUB;MSZ;MON;MOD;MB
B;MNT;LZT;LZS;LZN;LPV;LPN;LPL;LPC;LPA;LHT;LDP;LBA;KSB;KPV;KPA;KOE;KOB;KBU;KBL;KB;IAM;HZG;HZ;HSE;HRB;HFG;HF;HE;HAZ;GMD;GE
Z;GBB;FVT;FRM;FPL;FPK;FPI;FPA;FP;FMP;FME;FMD;FMA;FLP;FLB;FIM;FHW;FGY;FGV;FGS;FGP;FGL;FGK;FGE;FGD;FGB;FGA;FDA;FA;EZZ;EWZ;
EWS;EVT;EV;ETZ;ETL;ESZ;EPB;EP;ECM;DVL;ECR;DV;DRX;DRW;DRV;DRQ;DRK;DRF;DMD;DIF;DLP;DER;DDI;DBL;DB;DAT;D01;CPC;CIP;CHL;CE;C
AP;BVT;BVS;BVB;BV;BUG;BSV;BST;BSS;BS;BPZ;BLD;BDL;BBL;BBD;BB;BAL;BAD;ANH;AGZ;AFK;AEN;AED;AAW;AA;" == "!type:%~b=!" (
move /y "\server1\digit$\deposito\MFH3\MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf" "\bars
rv11\digit$\ok"
pause
)
endlocal
) )
if exist "\server1\digit$\deposito\MFH3\MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf" move
/y "\server1\digit$\deposito\MFH3\MFH3-AFK-20150511-F01MD12340-20301231-V07-OP20-TRIFLEX-CP1_H--.pdf" "\server1\
digit$\errori"
pause
)
1 file(s) moved.
Press any key to continue . . .
I need to delete duplicate folder names from a folder list. The duplicates occur when there's more than 1 subfolder. I end up with a list like below. I want to get rid of any line that has a sub2 folder.
folder1\sub1
folder2\sub1
folder2\sub1\sub2
folder3\sub1
Following code works if there is only one sub2 foldername, but it's awkward--hopeless if more than one sub2. There's gotta be a better way. Any help much appreciated.
#Echo off
SETLOCAL EnableDelayedExpansion
:: Write the sub2 foldernames to a tmp file
For /f "tokens=3 delims=\" %%I IN (folderlist.txt) DO Echo %%I >>temp.tmp
:: Set var for each sub2 name in tmp file and
:: call routine to write lines that don't contain that name
For /f %%G in (temp.tmp) do (
Set findstring=%%G
CALL :FindDup
)
EXIT
:findDup
For /f %%H in ('Type folderlist.txt ^|Find "!findstring!" /v') Do (
Echo %%H >> NoDup.txt
)
exit /b
FWIW: I'm using this command to generate the list, then deleting the path preceding folder1, folder2, etc
For /d %%G in (*) do dir /ad /on /s /b "%%G" >> folderlist.txt
you are almost there, if you just want the resulting list after eliminating the subfolders, just try to echo the appropiate lines to the list file, having copied it first into a temporary.
move folderlist.txt %temp%\folders.txt
for /f "tokens=1,2,* delims=\" %%a in (%temp%\folders.txt) do (
if .%%c==. echo %%a\%%b >>folderlist.txt
)
if you want to remove the folder from the disk, then change the line to
if not .%%c==. rd /s %%a\%%b\%%c
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%a IN (q20840158.txt) DO (
FOR /f "tokens=1,3delims=\" %%b IN ("%%a") DO IF "%%c"=="" ECHO(%%a
)
GOTO :EOF
I used a file named q20840158.txt containing your data for my testing.
But - It's really unclear what you mean by a "duplicate". How precisely do you define a duplicate in this context?
#ECHO OFF
SETLOCAL
COPY NUL newfile.txt >NUL 2>nul
FOR /f "delims=" %%a IN (q20840158.txt) DO (
ECHO %%a|FINDSTR /I /L /g:"newfile.txt" >NUL 2>NUL
IF ERRORLEVEL 1 >>"newfile.txt" ECHO(%%a
)
TYPE newfile.txt
GOTO :EOF
I used a file named q20840158.txt containing your data for my testing.
Produces newfile.txt
Ah- you want to make sure that any additions to the list don't contain a previous entry...
I am writing a batch file that finds and executes all update.bat file inside all the directories dropped onto it.
The problem here is that I expect the arguments (i.e directories' path) comes in ordered by name but it turns out they are sorted by the modified date.
Is this the default behavior of Windows (Windows 7)? Any suggestion to solve this?
Here is my batch script:
#echo off
Setlocal EnableDelayedExpansion
if [%1]==[] goto :no_update_dropped
set LOG_FILE=update_log.txt
echo You are about to run these updates:
for %%G IN (%*) do (
if exist %%~sG\NUL echo %%G
)
pause
for %%G IN (%*) do (
if exist %%G\NUL (
if exist %%G\update.bat (
call %%G\update.bat %LOG_FILE%
) else (
echo No update.bat found in %%G.
goto :no_batch_found
)
)
)
goto :success
:no_update_dropped
echo NO UPDATE FOLDER FOUND
echo Drag and drop one or more update folder to run.
goto :exit
:no_batch_found
echo UPDATE NOT COMPLETED!
goto exit
:success
echo all updated has been run successfully
goto :exit
:exit
pause
Best Regards.
You can sort your argument list right in your for loop like this:
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('(for %%i in (%*^) do #echo %%~i^)^|sort') do (
set dirname=%%a
set dirname=!dirname:~0,-1!
echo use "!dirname!" without the trailing space
)
P.S. It seems like sort appends a space to the end of string,(WTF ????) so you'll have to get rid of it. I changed the code.
Finally with the help of dbenham's explanation this becomes:
for /f "delims=" %%a in ('cmd /c "for %%i in (%*) do #echo %%~i"^|sort') do (
echo use "%%a"
)
P.P.S This should work safer with commas in names (of course, they must be quoted)
for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do #echo %%~i^"^|sort') do (
echo use "%%a"
)
I would change the input set.
You can order by name by using /on and to get directories
/ad
so all directories by name =
dir /ad /on