I'm looking to archive 10.0000+ files in a similar format:
files:
871-517-06461-1-120-01.pdf
871-517-06461-1-113-01.stp
871-517-06461-1-100-01.pdf
Example dir generated:
871-517-06461-1
NAV
TPD <- (files need to moved here)
INS
files:
871-517-21541-1-100-01.pdf
871-517-21541-1-110-01.pdf
871-517-21541-1-113-01.stp
Example dir generated:
871-517-21541-1
NAV
TPD <- (files need to moved here)
INS
What would be the way to archieve this? I came up with this:
#echo off
setlocal enabledelayedexpansion
for %%A in (*.pdf *.stp) do (
set data=%%A
echo file found !data:~0,16!
for /f "delims=" %%B in ("%%A") do set fname=%%~nB
for /f "delims=" %%C in ("%%A") do set fextn=%%~xC
for /f "tokens=1* delims=_" %%D in ("!fname!") do set folname=%%D
echo folder name !folname:~0,16!
if not exist "!folname:~0,16!" (
echo Folder !folname:~0,16! does not exist, creating
md "!folname:~0,16!"
md "!folname:~0,16!\TPD"
md "!folname:~0,16!\NAV"
md "!folname:~0,16!\INS"
) else (
echo Folder!folname:~0,16! already exists >> log.txt
)
echo Moving file %%A to folder !folname:~0,16!
move "%%A" "!folname:~0,16!\TPD"
)
echo Finished
pause
It's working, but how can i simplify this?
Also can i somehow change the character count with setting a variable?
Is it possible to remove the last - sign? So 871-517-06461-1 is named 871-517-064611.
Does this help you out?
It doesn't count characters, (yours should have been 15 anyway), it isolates everything up to the fourth hyphen/dash, -.
#Echo Off
SetLocal EnableExtensions
For /F "Delims=" %%G In (
'(Set PATHEXT^=^) ^& %SystemRoot%\System32\where.exe "%~dp0.":"?*-?*-?*-?*-*.pdf" "%~dp0.":"?*-?*-?*-?*-*.stp" 2^>NUL'
) Do For /F "Tokens=1-4,* Delims=-" %%H In ("%%~nG") Do (
For %%L In (INS NAV TPD) Do If Not Exist "%%~dpG%%H-%%I-%%J-%%K\%%L\" MD "%%~dpG%%H-%%I-%%J-%%K\%%L"
If Exist "%%~dpG%%H-%%I-%%J-%%K\TPD\" Move /Y "%%G" "%%~dpG%%H-%%I-%%J-%%K\TPD" 1>NUL
)
I haven't included all of the pointless echoing of messages, so you'll need to adapt it for those if you really need them. Please however, do not make such changes before you've tested it. The only thing you may need to change is the source path; the above uses %~dp0. for the same location as the running batch file, you could change that to just ., for the current directory, or an actual relative or absolute path, if you prefer, (taking care not to remove their enclosing double-quotes).
Related
I have went through a lot of guides for it, but havent found a way to do something similar to lets say turn all files in folder, like these files:
djhwu4s_cat_ruhg29.png
397y_dog_j0929_ej93.png
8yhh_owl.png
into these:
_cat.png
_dog.png
_owl.png
So basically removing everything from file names but a list of predefined strings i am searching for. In example above i would define list as "_cat", "_dog", "_owl". I know that each file will have only one of these variables, and there will be only one file with each of them in folder.
Will appreciate any tips on how to achieve that. Thanks in advance!
edit:
Here is what i came up with (with stuff i can understund) and what seems to be working fine now.
#echo off
setlocal enabledelayedexpansion
set v1=_cat-cat
set v2=_cat-owl
set v3=_cat
set v4=_dog
set v5=_owl
set v6=_horse
FOR /L %%a IN (1,1,6) DO (
rem echo %%a
rem echo !v%%a!
FOR /f %%f in ('dir /b /a:-D *!v%%a!.*') DO (
REN %%f !v%%a!.*
)
FOR /f %%f in ('dir /b /a:-D *!v%%a!_*.*') DO (
REN %%f !v%%a!.*
)
)
rem using two passes of this simpler code i can grasp and understund with dot and with underscore
rem after constructed variables value i make sure cat-cat is not recognised as and renamed to cat
rem no matter if im getting file with that variable as the last string before extension or another underscore
rem Gonna test it in combat now
For some reason this stuff doesnt work with files containing spaces and characters like:
"ab’c efg_dog.png"
FOR /L %%a IN (1,1,36) DO (
FOR /f %%f in ('dir /b /l /a:-D *!v%%a!.*') DO (
REN "%%f" "!v%%a!.*"
)
FOR /f %%f in ('dir /b /l /a:-D *!v%%a!_*.*') DO (
REN "%%f" "!v%%a!.*"
)
)
After further testing i have realised the problem starts with the %%f, and not the REN function as i thought. echo %%f before ren gives just the first part of the name to the first space, hence the REN function cant find the file. In case of "ab’c efg_dog.png" after finding the file with dir, the %%f becomes just "ab’c".
edit: After more tests and experiments and adding those "delims" to the code, the echo now shows proper, full names to be renamed, but it replaces that weird ’ character with ' for the REN command and thats why it still cant find the file to rename.
FOR /L %%a IN (1,1,36) DO (
FOR /f "delims=" %%f in ('dir /b /l /a:-D *!v%%a!.*') DO (
echo %%f
echo REN "%%f" "!v%%a!.*"
)
FOR /f "delims=" %%f in ('dir /b /l /a:-D *!v%%a!_*.*') DO (
echo %%f
echo REN "%%f" "!v%%a!.*"
)
)
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
PUSHD "%sourcedir%"
FOR /f "delims=" %%e IN ('dir /b /a-d "*_*" 2^nul ^|findstr /v /b "_"') DO (
FOR /f "tokens=2delims=_." %%y IN ("%%e") DO ECHO REN "%%e" "_%%y%%~xe"
)
POPD
GOTO :EOF
For lack of examples, here's a start.
Always verify against a test directory before applying to real data.
Process the list of filenames that match *_*; find those names that do not start _, pick the second string between the delimiters _ and . and rename using that string (in %%y), prefixed by _ and appended with the original extension.
The ren command is simply echoed to the screen for verification. When happy, remove the echo before the ren to actually execute the rename.
I already make script file for make new folder base on file name and move 1 file to this folder. The code as below.
#ECHO OFF
setlocal EnableExtensions DisableDelayedExpansion
set "sourcedir=C:\Users\XXX\4_MapIdentifyAndCSV"
set "destdir=C:\Users\XXX\5_OldData"
for /F "eol=| delims=" %%A in ('dir /B /A-D-H "%SourceDir%\*.csv" 2^>nul') do (
for /F "eol=| tokens=1 delims=." %%B in ("%%~nA") do (
md "%DestDir%\%%B" 2>nul
move /Y "%SourceDir%\%%A" "%DestDir%\%%B\"
)
)
endlocal
But I want to move another files from another directory to created folder too.
Example:
At C:\Users\XXX\2_Video move all file video to crated folder.
At C:\Users\XXX\Sub_Folder move all of Sub_Folder to crated folder.
And at C:\Users\XXX\3_Txt move all Text file to crated folder.
Please supporting me.
#ECHO OFF
setlocal EnableExtensions DisableDelayedExpansion
set "sourcedir=U:\Users\XXX"
set "destdir=U:\Users\XXX\5_OldData"
FOR %%s IN ("4_MapIdentifyAndCSV:.csv" "2_Video" "Sub_Folder" "3_Txt") DO FOR /f "tokens=1,* delims=:" %%t IN (%%s) DO (
for /F "delims=" %%A in ('dir /B /A-D-H "%SourceDir%\%%t\*%%u" 2^>nul') do (
for /F "tokens=1 delims=." %%B in ("%%~nA") do (
ECHO md "%DestDir%\%%B" 2>nul
ECHO move /Y "%SourceDir%\%%t\%%A" "%DestDir%\%%B\"
)
)
)
GOTO :EOF
I use U: for testing.
The eol=| is not required in your code, so I removed it.
The extra "shell" using %%s..%%u works this way:
The quoted string from the list is assigned to %%s. Each entry in the list is "subdirectoryname:filemask". : is chosen because it can't appear in either a subdirectory name or a filemask. The for ... delims=:... assigns the subdirectory name to %%t and the filemask to %%u. If the filemask is not provided, %%u will be empty.
From there, it's just a matter of piecing together the appropriate parts of the filenames and directories required, inserting * before the filemask to specify "all".
In this way, you can control the filetypes moved if required. It would appear that you want only the .csv files from one directory and all files from the others. You could also specify "4_MapIdentifyAndCSV:.csv" "4_MapIdentifyAndCSV:.xyz" within the list to move all .csv and all .xyz files if you wanted that.
Please note that the md and move commands ar merely echoed for testing purposes. Remove the echo keyword from each of those lines to activate the create/move.
I am not sure that I understand the requirements.
By modifying the list so that each element is
source_subdir:destination_subdir:filemask
we can achieve
4_map...*.csv -> 5_olddata\filename\filename.csv
2_vid...* -> 5_olddata\dest...2_vid...*
sub_f...* -> 5_olddata\dest...sub_f...*
3_txt...* -> 5_olddata\dest...3_txt...*
Of course, the actual destination subdirectory could be common if required - all that would be required is that the second element becomes common.
The .csv destination for the 4_map... source is derived from OP's original code.
Note that the destination_subdir must be a single space as a sequence of delimiters is processed as a single delimiter (: = :: = :::::::)
#ECHO OFF
setlocal EnableExtensions DisableDelayedExpansion
set "sourcedir=U:\Users\XXX"
set "destdir=U:\Users\XXX\5_OldData"
FOR %%s IN ("4_MapIdentifyAndCSV: :.csv" "2_Video:dest_for_2_video" "Sub_Folder:dest_for_sub_folder" "3_Txt:dest_for_3_text") DO FOR /f "tokens=1,2,* delims=:" %%t IN (%%s) DO (
for /F "delims=" %%A in ('dir /B /A-D-H "%SourceDir%\%%t\*%%v" 2^>nul') do (
IF "%%u"==" " (
rem if second element of list item is "empty", destination is directory ...\filename
for /F "tokens=1 delims=." %%B in ("%%~nA") do (
ECHO md "%DestDir%\%%B" 2>nul
ECHO move /Y "%SourceDir%\%%t\%%A" "%DestDir%\%%B\"
)
) ELSE (
rem if second element of list item is not "empty" it is the destination directory ...\%%u
ECHO md "%DestDir%\%%u" 2>nul
ECHO move /Y "%SourceDir%\%%t\%%A" "%DestDir%\%%u\"
)
)
)
I'm brand new to batch scripting so I appreciate any help. I've seen similar problems here but can't get my move function to work.
I have files with the following format:
19013_01-PG-18-1000_NC_IL2RG_Ex2_F_D01.ab1
19013_01-PG-18-1000_NC_IL2RG_Ex2_R_H01.ab1
I want to make folders with the following format:
01-PG-18-1000_NC_IL2RG_Ex2
And then move all the files that have *01-PG-18-1000_NC* into that folder name.
Here's what I have so far. It's making the folders the way I want, but I can't get the files to move at all. Tried multiple iterations of the move function, but I'm not totally understanding the tokens and how it relates to the files for moving.
#ECHO OFF
SETLOCAL
SET "sourcedir="whatever my directory name is"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3,4,5 delims=_" %%a IN (
'dir /b /a-d "*_*-*-*-*_*_*_*.*"'
) DO (
MD %%b_%%c_%%d_%%e 2>nul
MOVE "%%b_%%c_%%d_%%e" "%%b_%%c_%%d_%%e"
)
POPD
GOTO :EOF
Real quickie - and untested
#ECHO OFF
SETLOCAL
SET "sourcedir="whatever my directory name is"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3,4,5,* delims=_" %%a IN (
'dir /b /a-d "*_*-*-*-*_*_*_*.*"'
) DO (
echo ++%%a++%%b++%%c++%%d++%%e++%%f++
MD %%b_%%c_%%d_%%e 2>nul
MOVE "%%a_%%b_%%c_%%d_%%e_%%f" "%%b_%%c_%%d_%%e"
)
POPD
GOTO :EOF
You were very close - the echo line should show you how the filename is parsed into %%a..%%f. The parts separated by ++ which is simply a very obvious separator and shows whether there are spaces in any element.
Adding * to the token-list means "everything after the highest-mentioned token number". Then reconstruct the filename from the parts - string together starting at %%a, re-inserting all the underscores.
This should work also:
#ECHO OFF
SETLOCAL
SET "sourcedir="whatever my directory name is"
PUSHD %sourcedir%
FOR /f %%q IN (
'dir /b /a-d "*_*-*-*-*_*_*_*.*"'
) do (
FOR /f "tokens=1,2,3,4,5,* delims=_" %%a IN ("%%q") do
echo ++%%a++%%b++%%c++%%d++%%e++%%f++FROM++%%q++
MD %%b_%%c_%%d_%%e 2>nul
MOVE "%%q" "%%b_%%c_%%d_%%e"
)
)
POPD
GOTO :EOF
In this version, %%q acquires each filename in turn, then "%%q" can be parsed by for /f and the original filename remains unmolested in %%q ready for use in the move statement.
[actually, quite minor] Revision:
REM <!-- language: lang-dos -->
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
PUSHD "%sourcedir%"
FOR /f "tokens=1,2,3,4,5,* delims=_" %%a IN (
'dir /b /a-d "*_*-*-*-*_*_*_*.*"'
) DO IF EXIST "%%a_%%b_%%c_%%d_%%e_%%f" (
MD %%b_%%c_%%d_%%e 2>nul
MOVE "*%%b_%%c*" "%%b_%%c_%%d_%%e"
)
POPD
SET "sourcedir=U:\sourcedir\t h r e e"
PUSHD "%sourcedir%"
FOR /f %%q IN (
'dir /b /a-d "*_*-*-*-*_*_*_*.*"'
) do IF EXIST "%%q" (
FOR /f "tokens=1,2,3,4,5 delims=_" %%a IN ("%%q") DO (
MD %%b_%%c_%%d_%%e 2>nul
MOVE "*%%b_%%c*" "%%b_%%c_%%d_%%e"
)
)
POPD
GOTO :EOF
Yes - misread that you wanted to move all files containing - been up gaming all night...
The above batch is in two sections, the first using %%a..%%f and the second incorporating %%q.
The difficulty faced is that move *[pattern]* will move all of the files, as desired BUT for /f...'dir... builds a list of ALL of the matching files that were originally in the directory.
Once the first filename is processed, those other files containing the 01-PG-18-1000_NC will have been moved, so you'll get a "no files found" error on the next 01-PG-18-1000_NC file in the the list for has built.
Sure, it's possible to cruft together some mechanism for ensuring that the pattern 01-PG-18-1000_NC is only processed once, but a simple if exists for the full filename returned by for...%%a... and rebuilt can be used to gate the MD/MOVE commands as the file will no longer exist when the next 01-PG-18-1000_NC is processed (as it's already been moved). So much easier using the %%q method though.
Of course, you could also simply dispose of the error messages instead of installing a gate - but that's probably regarded as being crude.
Also aschipfl's suggestion of adding delims= to the for...%%q... is quite valid if you have separators like Space in your filenames (and costs nothing, regardless)
Oh - and I'd missed the ( in the do part in my initial response - always happens when you don't actually test the code, especially when you're tired.
I have a directory of academic papers that were named using the convention below:
Author1-(Year)-Title.pdf
For example,
Jones-(2011)-XXX.pdf
Smith-(2002)-YYY.pdf
Johnson-(2015)-ZZZ.pdf
I would like to rename them as
(2011)-Jones-XXX.pdf
(2002)-Smith-YYY.pdf
(2015)-Johnson-ZZZ.pdf
That is, to extract the year from the file name and put it in front.
I tried the following code, which did not work
Setlocal enabledelayedexpansion
Set "Year=2013"
Set "Replace="""
For %%a in (*.pdf) Do (
Set "NewName=(%year%)-%%~a"
Ren "%%a" "%NewName%-File:%Year%=%Replace%!"
)
Pause&Exit
In case XXX also contains hyphens I'd suggest using tokens=1,2* to stop parsing the remainder of the file name.
I'd also remove the parentheses, when the year is first place there is no need to further emphasize it.
#Echo off
for /f "tokens=1-2* delims=-()" %%A in (
'Dir /b "*-(*)-*.pdf"'
) do Ren "%%A-(%%B)-%%C" "%%B-%%A-%%C"
Sample output
> dir /b
2002-Smith-YYY.pdf
2011-Jones-XXX.pdf
2015-Johnson-ZZZ.pdf
Not tested
for /f "tokens=1,2,3 delims=-" %%a in ('dir /b "*.pdf"') do (
echo ren "%%a-%%b-%%c" "%%b-%%a-%%c"
)
this will only echo the intended rename command.If it looks ok remove the echo word.
Derived form this SO article - it works:
#ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%x IN (*.pdf) DO (
FOR /f "tokens=1-3 delims=-" %%a IN ("%%~x") DO (
SET "Author=%%a"
SET "Year=%%b"
SET "Title=%%c"
ren %%x !Year!-!Author!-!Title!
)
)
Here is a reliable way of doing what you are asking for even if the author part contains - on its own. The title portion may even contain ( and ), but the author part must not. So this is the code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILES=.\*-(????)-*.pdf" & rem // (basic pattern to match correct files)
set "_REGEX=^[^()][^()]*-([0123456789][0123456789][0123456789][0123456789])-.*\.pdf$" ^
& rem // (precise filter to exclude files violating the demanded pattern)
if not defined _REGEX set "_REGEX=.*" & rem // (avoid trouble with empty filter)
rem // Loop through all matching files:
for /F "eol=: tokens=1,2,* delims=()" %%F in ('
dir /B /A:-D "%_FILES%" ^| findstr /I /R /C:"%_REGEX%"
') do (
rem // Store the extracted file name parts:
set "LEFT=%%F" & set "YEAR=%%G" & set "REST=%%H"
setlocal EnableDelayedExpansion
rem // Reassemble the name and rename the file:
ECHO ren "!LEFT!(!YEAR!)!REST!" "(!YEAR!)-!LEFT!!REST:*-=!"
endlocal
)
endlocal
exit /B
After having verified the correct output, remove the upper-case ECHO command to actually rename files.
I have and will have files which are named "x_1.txt x_2.txt x_3.txt, ..." my other program where I input these files cannot recognize the order so it sorts like this "x_1.txt , x_101.txt , x_2.txt"). a solution is to rename the files to x00001.txt , x00002.txt , ....
I have so far wrote the .bat file below, but two problems I have which , I'd be very glad if you help me solve them :
1- how can I remove the 'number'.txt from string x_'number'.txt
2- (solved) how can I use the variable of this string to rename the file name ( the rename part of this file is not working!)
cls
setlocal enabledelayedexpansion
set /A count=100000
for %%f in (*.txt) do (
set /a count+=1
set str=!count:~1!
echo !str!
echo %%f
set filename=%%f
set filename=!filename:~0,5! /Comment: here I want to just keep the x_ part which I don't know how"
echo !filename!
set str3=!filname!!str!
echo !str3!
/// ren %%f !str3!.txt /Comment: Here I cannot use the variable str3,
call:renamer %%f !str3!
)
:renamer
ren %1 %2.txt
Thanks in advance
If the following conditions are true:
You want to rename all of your .txt files in the current folder
All of the .txt files have exactly one _ in the name, immediately before the number
None of your file names contain !
Then the following will work
#echo off
setlocal enableDelayedExpansion
for %%F in (*.txt) do for /f "tokens=1,2 delims=_." %%A in ("%%F") do (
set num=0000%%B
ren "%%F" "%%A!num:~-5!.txt"
)
But to eliminate the conditions requires much more complicated code.
Here is one robust solution that should properly rename all files that meet the template.
It allows for multiple _ in the name.
It only renames files with a name that ends with _NNN.txt where NNN is a number
It properly handles ! in the file name.
Note that it will not properly handle numbers that exceeds 99999. It is simple to expand the degree of 0 padding.
#echo off
setlocal disableDelayedExpansion
pushd .
subst #: .
#:
for /f "eol=: delims=" %%F in ('dir /b /a-d *.txt^|findstr /er "_[0-9]*.txt"') do (
set "name=%%~nF"
setlocal enableDelayedExpansion
for /f "eol=: delims=" %%A in ("!name:_=\x!") do (
endlocal
set "file=%%F"
set "name=%%~pA"
set "num=%%~nA"
setlocal enableDelayedExpansion
set "num=0000!num:~1!"
set "name=!name:~1,-1!"
ren "!file!" "!name:\x=_!!num:~-5!.txt"
endlocal
)
)
popd
subst /d #: