After asking this question on StackOverflow, I've written a .BAT-code that loops through all folders on a shared network drive, lists all files, then outputs HTML.
#echo off
setlocal enabledelayedexpansion
pushd %~dp0
(
echo ^<a href="javascript:toggleAll()" class='toggleAll' style="color:#f57832;" ^>Alles openen^</a^>
for /d /r %%a in (*) do (
pushd "%%a"
set "folder=%%a"
echo ^<h1 onClick="showHide($(this))" class="belangrijkeheader"^>!folder:~25!^</h1^>^<ul class='belangrijkelijst'^>
for /r %%b in (*) do (
set "filename=%%~nb"
set "filename=!filename: =%%20!"
echo ^<li^>^<a href="http://someurl.com:8081/somefolder/!folder:~25!/!filename!%%~xb"^>%%~nb^</a^>^</li^>
)
popd
echo ^</ul^>
)
)>"file.html"
start file.html
pause
It works pretty well, with the exception of subfolders. Each subfolder creates two entries. So, if we had a folder folder1 with two subfolders, subfolder1 and subfolder2 and both had a file, three things would be in the output
Folder1
fileinfolder1.jpg
fileinfolder2.jpg
Folder1/subfolder1
fileinfolder1.jpg
Folder1/subfolder2
fileinfolder2.jpg
I don't want the first entry, since the links are broken, and it doesn't show in what subfolder it is. However, I don't have a clue what to edit in my .bat file to make sure only the second two are shown.
Any assistance would be greatly appreciated.
Your problem is your inner loop is recursively listing all files within the current folder (including subfolders).
All you need to do is remove the /R option.
incorrect
for /r %%b in (*) do (
correct
for %%b in (*) do (
Note - You have additional potential problems.
File names containing ! will fail because delayed expansion will corrupt the FOR variable expansion.
I think there are a number of url encoding issues that you have not addressed, since file names can contain + and %. There may be other issues.
Related
Coding is not my speciality but I have come across a problem and google search has guided me to using batch file process in solving it. Essentially I have a couple of thousands of files that need to be moved into folders and they have a very simple file structure, listed below:
UK--London--Filename.pdf
UK--London--Filename2.pdf
UK--Manchester--Filename3.pdf
UK--Liverpool--Filename4.pdf
UK--Chester--Filename5.pdf
I would like the script to:
1. Pick up the first "--" check if the folder exists, if not create it
2. Pick up the second "--" check if the folder exists, if not create it
3. As there might be more than two "--", ignore the rest
4. Move file into the subfolder
To that end, the output should be some like (note "FILETEST" is the folder I am using to test the script):
C:\FILETEST\UK\London\UK--London--Filename.pdf
C:\FILETEST\UK\London\UK--London--Filename2.pdf
C:\FILETEST\UK\Manchester\UK--Manchester--Filename3.pdf
C:\FILETEST\UK\Liverpool\UK--Liverpool--Filename4.pdf
C:\FILETEST\UK\Chester\UK--Chester--Filename5.pdf
I have had an attempt to re-using a script from another question in stackoverflow (Batch create folders based on part of file name and move files into that folder). I understand that it would not do exactly what I need, but cant seem to get any output.
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\FILETEST"
PUSHD %sourcedir%
FOR /f "tokens=1*delims=--" %%a IN (
'dir /b /a-d *.*.*'
) DO (
ECHO MD %%a
ECHO MOVE "%%a.%%b" --\%%a\
)
POPD
GOTO :EOF
Apologies for any headaches caused, I am hoping this is a simple one to solve.
Thank you,
Panos
#ECHO OFF
SETLOCAL
SET "sourcedir=c:\FILETEST"
PUSHD %sourcedir%
FOR /f "tokens=1,2*delims=-" %%a IN (
'dir /b /a-d *--*--*.*'
) DO if "%%c" neq "" (
ECHO MD "%%a"
ECHO MD "%%a\%%b"
ECHO MOVE "%%a--%%b--%%c" ".\%%a\%%b\"
)
POPD
GOTO :EOF
Read the directory list of files in the current directory, (/a-d = no directorynames) that match *--*--*. Tokenise so that %%a acquires the part before the first --sequence, %%b the second and %%c the remainder.
If %%c is not empty then make the directories ".\%%a" and ".\%%a\%%b" (quoted because any spaces in the name would otherwise be seen as "create two directories") then move the file, again quoted for the same reason.
Note that each character individually between delims= and the close-quote is a delimiter - a delimiter-string is not supported. Consequently, this code will pick up - as well as --- and any other sequence of - and try to process it. You could gate the create/move further by adding if exist "%%a--%%b--%%c" directly after the if "%%c" neq ""before the (.
The md will create a directory if the target name does not already exist, and produce an error-message if it already exists. To suppress the error message, append 2>nul to the md lines.
this is my first post as im having a little trouble with a batch file to loop through subfolders and use the subfolder name as a variable in a command. I have managed to get the code well enough advanced and it runs, but continually repeats running with the last folder name in the main directory. It doesn't find and cycle through the other subfolders.
SETLOCAL EnableDelayedExpansion
SET MYPATH=H:\RAWBDA\001076\host
for /d %%a in (%mypath%\*) do set "folderName=%%a"
echo %folderName%
for /d %%f in (%folderName%) do set myfolder=%%~nxf
echo %myfolder%
FOR /d /r %%i IN ('DIR /B %mypath%*.tif') DO (
trial.exe "%foldername%\%myfolder%_B4.tif" "%foldername%\%myfolder%_B3.tif" "%foldername%\%myfolder%_B2.tif" "%foldername%\%myfolder%_B432.tif"
)
I beleive the problem is that the FolderName and myFolder are outside the loop, but i cant get them to dynamically update within the loop.
Very grateful for some help.
The solution is simple: enumerate the subfolders and to get their names use a prefix %%~nx:
SET "MYPATH=H:\RAWBDA\001076\host"
rem Using quotes around "var=value" in case the path may contain spaces
for /d %%a in ("%mypath%\*") do (
echo Folder name: %%~nxa, full folder path: %%a
trial.exe "%%a\%%~nxa_B4.tif" "%%a\%%~nxa_B3.tif" "%%a\%%~nxa_B2.tif" "%%a\%%~nxa_B432.tif"
)
At work we use a bespoke program to search through a directory tree and find an individual image file. These files are stored in folders that have a 7-digit name, starting with '18' - so for instance '1873456', '1873457', '1873458' etc. The problem I have is at some point last year the procedure that creates these folders and populates the images in them reached '1899999' - and then rolled over to '18100000' and carried on like that for over 4,000 folders before it was caught and corrected.
The bespoke program we use can only handle seven-digit folder names. What I would like to do is create a batch file that renames all the eight-digit folders by removing the extra '1' in the name, so '18100000' becomes '1800000' and so forth until '18104013' becomes '1804013'.
Can anyone help?
Run this in the base folder, it will not change any folders.
A file called renfile.bat.txt will be created that contains the rename command for the folders that match the filespec. Examine it in notepad to see if it is ok and then rename it to renfile.bat and run it.
It's not tested.
#echo off
setlocal enabledelayedexpansion
for /d /r %%a in (18??????) do (
set "name=%%~nxa"
>>renfile.bat.txt echo ren "%%a" "!name:~0,2!!name:~3!"
)
Something like
for /l %%x in (100000,1,104013) do (
set oldsuffix=%%x
set newsuffix=%oldsuffix:~-5%
ren 18%%x 18%newsuffix%
)
setlocal enableextensions enabledelayedexpansion
for /d /r "c:\somewhere" %%f in (181?????) do (
set "name=0" & set /a "name+=%%~nf" 2>nul
if !name! gtr 1899999 ren "%%~ff" "18!name:~-5!"
)
I am trying to create a batch script on windows 7 to do the following:
I have a folder which another program dumps files to.
All the files have numbers in their name along with other identifying information.
I would like to have a batch script search for all the digits in the file name and then create a folder (folder name is just the digits) and move all files that contain those digits to the folder.
It must be applicable to numerous users in my office.
currently i have a very bad primitive system running which doesn't account for mistakes:
#echo off
setlocal enabledelayedexpansion
pushd "%USERPROFILE%\Desktop\RawFiles"
for %%a in (*) do (
set fldr=%%~na
set fldr=!fldr:~0,5!
md "!fldr!"
move "%%a" "!fldr!"
)
popd
if not exist "%USERPROFILE%\Dropbox\agents" mkdir "%USERPROFILE%\Dropbox\agents"
SET "src_folder=%USERPROFILE%\Desktop\RawFiles"
SET "tar_folder=%USERPROFILE%\Dropbox\agents"
for /f %%a IN ('dir "%src_folder%" /b') do move /-y %src_folder%\%%a %tar_folder%
exit
the files in the "rawfiles" folder are as follows:
12345 - tech pack.pdf
12345.pdf
12345-artwork.AI
"#12345- artwork.AI"
What i created only works for perfect instances where the numbers come first in files and are exactly 5.
Unfortunately there is a lot of human error here so this solution is not viable.
an example of a mistake is an accidental 6 digit number or even putting the "#" sign before the numbers
I also would like to be able to override the files in the destination folder by running this twice but am getting "access denied".
Please help!
thanks
The Batch file below extract the digits from the file names as requested (maximum 6 groups of digits separated by other characters, this may be modified), so you may manipulate they in any way you wish; the ECHO commands are just examples. Note that the space must be the last character in eliminate variable.
#echo off
setlocal EnableDelayedExpansion
set "eliminate=#-abcdefghijklmnopqrstuvwxyz "
for %%a in (*.*) do (
for /F "tokens=1-6 delims=%eliminate%" %%b in ("%%~Na") do set folder=%%b%%c%%d%%e%%f%%g
if not exist "!folder!" ECHO md "!folder!"
ECHO move "%%a" "!folder!"
)
The code below works fine, here is a list of it's functions:
It moves files based on the fist 4 characters to a pre-created folder with the same first 4 characters
If the folder does not exist, it will not move the file, as there is no folder with the same fist 4 chars.
#echo on
setlocal enabledelayedexpansion
cls
pushd R:\Contracts\Sites
for /f "tokens=*" %%1 in ('dir /a-d /b *') do (
set filename=%%1&set dirname=!filename:~0,4!
for /f "tokens=*" %%A in ('dir /ad /b') do (
set dirid=%%A & set dirid=!dirid:~0,4!
if "!dirid!" equ "!dirname!" move %%1 %%A
)
)
I would like to add one extra function to this code please. Pleas have a look at the example below.
I have 5 files
X32A-test.docx or X32A-test.pptx (there will only be one docx or pptx, "NEVER two with the same name")
X32A-test.pdf
X32A-test.avi
X32A-test-eng.sub
X32A-test-small.jpg
I would like the code to CREATE a folder if it does not exist, based on the file name if it has the extension docx or pptx.
So with the above example it would create a folder named: "X32A-test". Then all the other files with "X32A" in the front of the name will be moved to that newly created folder "X32A-test".
I hope it is clear enough. If not please ask me for more information.
Thank you
It is much simpler and more efficient to use the simple FOR instead of FOR /F in your case.
And rather than looping through every file and moving them individually, it is easier and more efficient to use wildcards.
The first loop finds the .pptx and .docx files and creates folders as needed
The second loop finds all the directories and moves all files that start with the directory name into the directory.
#echo on
setlocal enableDelayedExpansion
cls
pushd R:\Contracts\Sites
for %%F in (*.docx *.pptx) do (
set "folder=%%F"
2>nul md !folder:~0,4!
)
for /d %%F in (*) do move %%F* %%F
popd
If needed, you can protect yourself against directory names shorter than length 4.
#echo on
setlocal enableDelayedExpansion
cls
pushd R:\Contracts\Sites
for %%F in (*.docx *.pptx) do (
set "folder=%%F"
set folder=!folder:~0,4!
if !folder:~0,3! neq !folder! 2>nul md !folder!
)
for /d %%F in (????) do (
set "folder=%%F"
if "!folder:~0,3!" neq "%%F" move %%F* %%F
)
popd
Note that this solution may fail if a file name contains !. If that arises then you need to toggle delayed expansion on and off within the loop(s).
I can see the entire process (including the part already implemented) like this:
All the files that are not yet in their "home" directories are moved there.
For all .docx and .pptx files left, create directories based on the files' names.
Obviously, the step #2 creates new "homes" and those will still be "uninhabited" this far. So all that is left to do now is to repeat the step #1.
So I would probably reorganised your process and, with the additional requirement, it could be implemented this way:
…
PUSHD your_root_directory
FOR /D %%D IN (*) DO (
CALL :movefiles "%%D"
)
FOR %%F in (*.docx *.pptx) DO (
MKDIR "%%~dpnF"
CALL :movefiles "%%~dpnF"
)
…
GOTO :EOF
:movefiles
SET "dirname=%~n1"
SET "mask=%dirname:~0,4%*"
MOVE "%~dp1%mask%" %1
Note: The steps #2 and #3 could be either implemented as separate loops or combined in one. The above script uses the latter approach.
You can use negative offsets in the !var:~offset,len! evaluation as follows:
set fspec=X32A-test.docx
echo !fspec:~-10!
echo !fspec:~0,-10!
That second line above gives you -test.docx and you can simply check that against your two desired possibilities with an if statement (or two).
Then you can use the third line to get the rest of the name for creating a directory.
The following example script shows how this could be done:
#setlocal enableextensions enabledelayedexpansion
#echo off
set fspec=X32A-test.docx
set bit1=!fspec:~-10!
set bit2=!fspec:~0,-10!
if .!bit1!.==.-test.docx. echo mkdir !bit2!
if .!bit1!.==.-test.pptx. echo mkdir !bit2!
endlocal
I'm echoing the mkdir command rather than executing it so you need to take out the echo. You'll also need to integrate the set and if statements into your loop but, based on what you have so far, you should have little trouble with that.
If, as you seem to indicate in a comment, the first four characters are the key and the last five decide on whether to make the directory, as in:
x32s-test.docx
a21w-production.pptx
xxxx-whatever_the_blazes_you_want.some_other_rubbish.docx
Then you're really only interested in the first four and last five:
#setlocal enableextensions enabledelayedexpansion
#echo off
set fspec=a12b-whatever_the_blazes_you_want.some_other_rubbish.docx
set bit1=!fspec:~-5!
set bit2=!fspec:~0,4!
if .!bit1!.==..docx. echo mkdir !bit2!
if .!bit1!.==..pptx. echo mkdir !bit2!
endlocal
This checks the correct extensions and outputs:
mkdir a12b
as expected.