Pare down a variable to all before 1st space - windows

BACKGROUND:
Have the following code. Lines 5 & 6 are the most important here:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
move /Y "Folder2.jpg" "Folder.jpg"
This line 5 for %%I in (.) do set "FOLDER=%%~nxI"
This line 6 "%ProgramFiles(x86)%\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive "%~dp0zzzGDB.sqlite3" "https://www.pixiv.net/en/users/%FOLDER%/illustrations"
if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"
popd
endlocal
In Windows Explorer I create a folder (for example) named "18604150". Any folders I create will have a folder name of varying lengths. The code above is in a .bat file within that folder. Upon executing the code, line 5 assigns folder name "18604150" to the variable and line 6 inserts/calls it as part of the hyperlink:
https://www.pixiv.net/en/users/%FOLDER%/illustrations
equates to
https://www.pixiv.net/en/users/18604150/illustrations
All is well.
PROBLEM:
I want to be able to ALWAYS name folders as with the aforementioned numerical string at the beginning but IN SOME CASES also manually append artist name and/or other details to the folder name. Problem is I need to do this without "breaking" the variable and making it unusable for the hyperlink. Folder names could take on many shapes but will always begin with an unbroken first string of numbers. Examples:
18604150 -59 Bob Marley-
4839 Dan the Man
19374759394727 Scooby Snack 43443
I need to pare the variable down to only the digits left of any first SPACE, when present.
18604150
4839
19374759394727
I'm guessing whatever the solution will likely have to be in Line 5, but I do not know what this would look like.
for %%I in (.) do set "FOLDER=%%~nxI"

A little trial and error got my answer. Thanks goes to https://www.dostips.com/DtTipsStringManipulation.php
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
move /Y "Folder2.jpg" "Folder.jpg"
for %%I in (.) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set FOLDER=%%a
"%ProgramFiles(x86)%\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive "%~dp0zzzGDB.sqlite3" "https://www.pixiv.net/en/users/%FOLDER%/illustrations"
if not errorlevel 1 if exist "zzzGDB.sqlite3" del "Folder.jpg"
popd
endlocal
pause

Related

How to create folder name without extension of file type using batch script and move in created sub directory?

Help me sir i try more than 100 times but it not exactly works for me.
Currently getting results in wrong way:-
Given below batch script create folder from this file (7101-1- kutana.pdf) name with .pdf extension but not exactly what i need.
Results i need in right way a/q to given below steps
For example
Step 1:-I want to remove 1st five character from file name (7101-1- kutana) and also i want to remove extension from folder name.
Sourcedir=e:\automovesystem\temp
A. source pdf file name :- 7101-1- kutana.pdf
Step 2:-
Create directory under destdir name of 1-(space)kutana and award
B. destdir=e:\automovesystem\prpl
Created directory e:\automovesystem\prpl\1- kutana\award
Step3.check if already folder name available according to step 1 file name.
Step 4: - move same file in same folder which is created in step 2 under sub directory.
#echo off setlocal enableextensions disabledelayedexpansion
Set "sourcedir=e:\automovesystem\temp"
Set "destdir=e:\automovesystem\prpl"
For /f "eol=| tokens=1* delims=-" %%a in ('dir /b /a-d-h "%sourcedir%\*-*" 2^>nul') do (
Md "%destdir%\%%b\award" 2>nul
Move /y "%sourcedir%\%%a-%%b" "%destdir%\%%b\award" )
Endlocal
Additional to your own answer, I probably would have done it a litte more like this:
#Echo Off
SetLocal EnableExtensions
Set "SRC=E:\automovesystem\TEMP"
Set "DST=E:\automovesystem\PRPL"
If Not Exist "%SRC%\" (Exit /B) Else If Not Exist "%DST%\" Exit /B
For /F "Delims=" %%G In ('%SystemRoot%\System32\where.exe "%SRC%":"????-?*-?*.*"
2^>NUL') Do For /F "Tokens=1,* Delims=-" %%H In ("%%~nG"
) Do %SystemRoot%\System32\Robocopy.exe "%%~dpG." "%DST%\%%I\NOTICE" "%%~nxG"^
/Mov 1>NUL 2>&1
All help with this goes to #XionicFire he reworked the whole of this code I'm just posting it for others to use/benefit:
This code comes from a mix of several different people #PrahladDixit & #Compo, the code was not working we couldn't tell why after a LOT of search seems it suffered the usual... "a pro wrote this so no one understands what he did" syndrome, where us worms cannot figure it out, we remade it and organized it so normal human "worms" can understand what its doing and made it a little friendlier so its easier to mod and change as needed, we hope this helps others, works great in windows 11
Code
#ECHO OFF
ECHO This file will create Individual folders inside the current folder using the following Parameters and sort all *.JPG files in current directory accordingly
REM To change target or source directory simply type it in the variable field
SET "SRC=%~dp0"
SET "SRC=%SRC:~0,-1%"
SET "DST=%~dp0"
SET "DST=%DST:~0,-1%"
ECHO.
REM For Diagnostics & Troubleshooting Purposes
ECHO Source: %SRC%
ECHO Destination: %DST%
ECHO Characters: 19
ECHO Where: %SystemRoot%\System32\where.exe "%SRC%":*.jpg
ECHO.
ECHO To Cancel this operation press CTRL-C
PAUSE
SetLocal EnableDelayedExpansion
If Not Exist "%SRC%\" (Exit/B) Else If Not Exist "%DST%\" Exit/B
For /F "Delims=" %%A In ('%SystemRoot%\System32\where.exe "%SRC%":*.jpg') Do (
SET "FNX=%%~nA"
REM Replace 19 for the number of characters from the start of the filename you wish to use as Base for folder creation
SET "FNX=!FNX:~,19!
REM For Diagnostics & Troubleshooting Purposes
REM ECHO !DST!\!FNX!\
If Not Exist "!DST!\!FNX!\" (MD "!DST!\!FNX!" 2>NUL
If ErrorLevel 1 ECHO Unable to create directory !DST!\!FNX!)
If Exist "!DST!\!FNX!\" (MOVE /Y "%%A" "!DST!\!FNX!">NUL 2>&1
If ErrorLevel 1 ECHO Unable to move %%A to !DST!\!FNX!)
)
ECHO ************************ DONE ************************
PAUSE
REM Use in the case of running multiple scripts in a row
REM EXIT/B
I had less knowledge of batch scripting that's why not sleep from yesterday continue
working on to make AutoMoveFilesystem but also i am great thankful to provide stack overflow platform to create this code. i can't able to do without this plateform.
#Echo Off
Set "SRC=E:\automovesystem\TEMP"
Set "DST=E:\automovesystem\PRPL"
SetLocal EnableDelayedExpansion
If Not Exist "%SRC%\" (Exit/B) Else If Not Exist "%DST%\" Exit/B
For /F "Delims=" %%A In ('Where "%SRC%":?????????*.*') Do (Set "FNX=%%~nA"
If Not Exist "%DST%\!FNX:~5,50!\NOTICE" (MD "%DST%\!FNX:~5,50!\NOTICE" 2>Nul
If ErrorLevel 1 Echo Unable to create directory %DST%\!FNX:~5,50!\NOTICE)
If Exist "%DST%\!FNX:~5,50!\NOTICE" (Move /Y "%%A" "%DST%\!FNX:~5,50!\NOTICE">Nul 2>&1
If ErrorLevel 1 Echo Unable to move %%A to %DST%\!FNX:~5,50!\NOTICE))
Timeout -1
Exit/B

Move files batch doesn't work with double click but works from command line

I have some files
afjj.txt
agk.png
beta.tt
Ritj.rar
I use this script to move files in alphabetically order into autogenerated folders
a
|
|----> afjj.txt
|----> agk.png
b
|----> beta.tt
R
|----> Ritj.rar
To do I use this code
#echo off
setlocal
for %%i in (*) do (
set name=%%i
setlocal enabledelayedexpansion
if not "!name!" == "%0" (
set first=!name:~0,1!
md !first! 2>nul
if not "!first!" == "!name!" move "!name!" "!first!\!name!"
)
)
What is problem? If I double-click on this batch, batch doesn't work, not move.
But this batch works from command line.
Why?
NOTE: I use Windows Server 2016
P.S: from command line I use this command and works but not if I double click directly on .bat
move.bat "Z:\# 2020\Alfa\test"
The first mistake is naming the batch file move.bat. It is never a good idea to give a batch file the name of a Windows command because hat cause usually troubles. See also: SS64.com - A-Z index of Windows CMD commands.
The second mistake is using setlocal enabledelayedexpansion inside the loop without a corresponding endlocal also within same loop executed as often as setlocal. Please read this answer for details about the commands SETLOCAL and ENDLOCAL. The command SETLOCAL pushes several data on stack on every iteration of the loop and the data are never popped from stack in same loop on each loop iteration. The result is sooner or later a stack overflow depending on the number of files to process as more and more data are pushed on stack.
The third mistake is the expectation that the current directory is always the directory of the batch file. This expectation is quite often not fulfilled.
The fourth mistake is using a loop to iterate over a list of files which permanently changes on each execution of the commands in body of FOR loop. The loop in code in question works usually on storage media with NTFS as file system, but does not work on storage media using FAT32 or exFAT as file system.
The fifth mistake is the expectation that %0 expands always to name of the currently executed batch file with file extension, but without file path which is not true if the batch file is executed with full qualified file name (drive + path + name + extension), or with just file name without file extension, or using a relative path.
The sixth mistake is not enclosing the folder name on creation of the subfolder in double quotes which is problematic on file name starting unusually with an ampersand.
The seventh mistake is not taking into account to handle correct file names starting with a dot like .htaccess in which case the second character must be used as name for the subfolder, except the second character is also a dot. It is very uncommon, but also possible that file name starts with one or more spaces. In this case also the first none space character of file name should be used as Windows by default prevents the creation of a folder of which name is just a space character.
The solution is using following commented batch file with name MoveToFolders.cmd or MyMove.bat.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Get folder path of batch file assigned to an environment
rem variable. This folder path ends always with a backslash.
set "FilesFolder=%~dp0"
rem Optionally support calling of this batch file with another folder
rem path without checking if the passed string is really a folder path.
if not "%~1" == "" set "FilesFolder=%~1"
rem Replace all / by \ as very often people use / as directory separator
rem which is wrong because the directory separator is \ on Windows.
set "FilesFolder=%FilesFolder:/=\%"
rem The folder path should end always with a backslash even on folder
rem path is passed as an argument to the batch file on calling it.
if not "%FilesFolder:~-1%" == "\" set "FilesFolder=%FilesFolder%\"
rem Get a list of files in specified folder including hidden files loaded
rem into the memory of running command process which does not change on
rem the iterations of the loop below. Then iterate over the files list and
rem move the files to a subfolder with first none dot and none space character
rem of file name as folder name with the exception of the running batch file.
for /F "eol=| delims=" %%i in ('dir "%FilesFolder%" /A-D /B 2^>nul') do if /I not "%FilesFolder%%%i" == "%~f0" (
set "FileName=%%i"
set "FirstPart="
for /F "eol=| delims=. " %%j in ("%%i") do set "FirstPart=%%j"
if defined FirstPart (
setlocal EnableDelayedExpansion
set "TargetFolderName=%FilesFolder%!FirstPart:~0,1!"
md "!TargetFolderName!" 2>nul
if exist "!TargetFolderName!\" move "%FilesFolder%!FileName!" "!TargetFolderName!\"
endlocal
)
)
rem Restore the previous execution environment.
endlocal
The batch file can be started also with a folder path as argument to process the files in this folder without checking if the passed argument string is really referencing an existing folder.
Please read very carefully the answers on How to replace a string with a substring when there are parentheses in the string if there is interest on how to verify if a passed argument string really references an existing folder.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
dir /?
echo /?
endlocal /?
for /?
if /?
md /?
move /?
rem /?
set /?
setlocal /?
Here is a slightly amended script. Notice I removed the !first! variable as it is not required. I also built in a safety measure, if it is unable to pushd to the given directory you passed to %~1 it will not continue the move. Else it might move files in a path you do not want it to move files. i.e the working dir you started the script in.
#echo off
setlocal enabledelayedexpansion
pushd "%~1" && echo( || goto :end
for %%i in (*.test) do (
set "name=%%~ni"
if not "%%~nxi" == "%~nx0" (md !name:~0,1!)2>nul
if not "!name:~0,1!" == "%%~i" move "%%~i" "!name:~0,1!\%%~i"
)
popd
goto :eof
:end
echo The directory you entered does not exist. Exited script..
pause
Note, with the above you can also drag a directory to the batch file, which will process that directory.
Or if you plan on double clicking, without parameters from cmd.
#echo off
setlocal enabledelayedexpansion
for %%i in (*.test) do (
set "name=%%~ni"
if not "%%~nxi" == "%~nx0" (md !name:~0,1!)2>nul
if not "!name:~0,1!" == "%%~i" move "%%~i" "!name:~0,1!\%%~i"
)
pause
A slightly different take.
This script will work on the current directory if double clicked, or run at the command line without a path specified.
But it will also allow you to provide a path to it as well.
#( SETLOCAL ENABLEDELAYEDEXPANSION
ECHO OFF
SET "_PATH=%~1"
IF NOT DEFINED _PATH SET "_PATH=%CD%"
)
CALL :Main
( Endlocal
Exit /B )
:Main
For /F "Tokens=*" %%_ in ('
DIR /B/A-D-S-H-L "%path%"
') DO (
IF /I "%%_" NEQ "%~nx0" (
SET "_TmpName=%%_"
IF NOT EXIST "%_Path%\!_TmpName:~0:1!\" MD "%_Path%\!_TmpName:~0:1!\"
MOVE /Y "%_Path%\!_TmpName!" "%_Path%\!_TmpName:~0:1!\!!_TmpName!"
)
)
GOTO :EOF
Based upon only filenames beginning with alphabetic characters, here's a somewhat simpler methodology:
#Echo Off
SetLocal EnableExtensions
PushD "%~1" 2> NUL
If /I "%~dp0" == "%CD%\" (Set "Exclusion=%~nx0") Else Set "Exclusion="
For %%G In (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) Do (
%SystemRoot%\System32\Robocopy.exe . %%G "%%G*" /Mov /XF "%Exclusion%" 1> NUL 2>&1
RD %%G 2> NUL
)
PopD

Get a part of the current path

I would like to get a part of the current directory where my batch script is from.
The location is something like this : Y:\abc\def\ghi\jkl\script.bat
I just want to keep what's after Y:\abc\def\  (that is \ghi\jkl)
How to do this ?
I'm using the code below for getting the full path but how to make a delimitation ?
for /f %%a in ("%CD%") do set CURR=%%a
echo %CURR%
Thank you for your precious help.
Based upon your stated "directory where my batch script is from", the following should suffice, (the last line is added for demonstration purposes, please change it as necessary):
#Set "x=%~dp0"&SetLocal EnableDelayedExpansion
#Set "i=0"&Set "x!i!=%x:\="&Set /A i+=1&Set "x!i!=%"
#Set /A i-=1,y=i-1
#If %i% Lss 1 (Set "z=%x0%\")Else (If %i% Equ 1 (Set "z=%x0%\%x1%"
)Else Set "z=!x%y%!\!x%i%!")
#EndLocal&Set "y=%z%"
#Echo %x% becomes %y%&Pause
I have made it so that if the scripts directory isn't deep enough, the full path will still be output.
If you want to use the current directory instead of the scripts location, change %~dp0 on line 1 to %__CD__% or %CD%\ as needed.
I believe that maybe you could put the section to be cut inside a txt file and then manipulate the string from the loop in the file, like this:
echo %cd% > path.txt
for /f "tokens=3,* delims=\" %%a in (path.txt) do echo %%b
Determining the depth with the argument tokens=3 with the delimiter character being "\".
#echo off
setlocal
set "reversed="
set "fromdir=%~dp0"
for %%A in ("%fromdir:\=" "%") do call set "reversed=%%~A\%%reversed%%"
for /f "tokens=1-2 delims=\" %%A in ("%reversed%") do set "result=\%%B\%%A"
echo %result%
pause
If the path segments can be reversed, then getting the last 2 segments is a known number for setting the tokens option of 1-2 as they would become the 1st 2 segments. The 1st for loop does the reversing. The 2nd for loop gets the 1st 2 tokens and is set to result in reverse order, which is the original order.
The fromdir is set for the script directory %~dp0, though it can be set with %cd% if is wanted.
View set /? for how "%fromdir:\=" "%" does replacement of \ with " " so that the path segments become individual arguments i.e. "C:\dir1\dir2\dir3" becomes "C:" "dir1" "dir2" "dir3".

Adding a textfile with a name to each directory

I'm having some trouble with trying to add a text file to each directory in this directory having a certain name. I have a directory called Daily Notes where I save my notes for the day and I have this further organized by week. So I have a bunch of directories in here such as 6.5.17-6.10.17 and in each of these I need a text file with the name format such as 6.7.17DailyNotes.txt. I know I can easily do this by hand each day, but I have some free time and am trying to learn how to program with cmd. I tried to just make a test text file with a for loop but it saved it to the directory containing the batch file. Here is my code right now:
#echo off
setlocal disabledelayedexpansion
set "folder=%~1"
if not defined folder set "folder=%cd%"
for /D %%a in ("%folder%\*") do (
echo test > test.txt
)
endlocal
So, I want to go into each directory and make 5 text files, one for each day with the format month.day.yearDailyNotes.txt. I was thinking I could just make a variable from reading the directory name and count up in days from that for the text files. Any advice?
Your comment
I know it would be very difficult to handle month changes in the
middle of the week, I was thinking it will be acceptable to just
handle that part manually, so have a file named something like
10.32.17DailyNotes.txt which I manually will change after
makes it much easier (Date/Time Math in Batch is possible, but ugly and involves a lot of code)
#echo off
setlocal enabledelayedexpansion
REM next two lines for simulating your environment:
set "folder=%~dp0"
md 6.5.17-6.10.17 6.11.17-6.16.17 2>nul
REM for every folder
for /d %%f in ("%folder%*.*.*-*.*.*") do (
REM extract day, month and year [from first part of foldername]
for /f "tokens=1-3 delims=.-" %%a in ("%%~nxf")do (
REM calculate "end day" [may be greater than days in that month]
set /a end=%%b+5
REM for [start] to [end]
for /l %%i in (%%b,1,!end!) do (
REM create blank file
break > "%%f\%%a.%%i.%%cDailyNotes.txt"
)
)
)
Iterate over all of the subdirectories and create a test.txt file.
set "folder=%~1"
if not defined folder set "folder=%cd%"
FOR /F "usebackq tokens=*" %%a IN (`DIR /S /B /A:D "%folder%\*"`) DO (
ECHO test > "%%~a\test.txt"
)
#echo off
setlocal disabledelayedexpansion
set "folder=%~1"
if not defined folder set "folder=%cd%"
for /D %%q in ("%folder%\*") do (
echo test "%%q\%%~nxqDailyNotes.txt"
)
ENDLOCAL
Interesting exercise with a couple of twists.
my posted code will simply show 'test "fullfilename" '. Naturally, you could use copy nul "*fullfilename*"' to create an empty file (with>nulto suppress the creation-report) orecho.>"fullfilename"` to create a file containing just an empty line - or whatever.
The main magic is with the gymnastics in creating the filename. Since you are using for/d, the directoryname will appear in %%q. so the required filename is the name+extension part of that directoryname (you and I know it's actually not a filename but the outermost leafname of a directory tree - just don't tell cmd) so we use %%~nxq meaning the name and extension part of the "filename" in %%q (see for /?|more from the prompt for documentation). We then just tack the remainder of the required name on as a literal.
So - why the change to %%q?
Suppose we leave it as %%a. The filename would then be "%%~nxaDailyNotes.txt" and be interpreted as name,extension,attribute,drive of %%a since i is neither a modifier nor a participating metavariable. Changing the metavariable from %%a to %%q removes the misinterpretation.

Windows Batch File - Display All Folder & Sub-Folder relative paths

I am trying to have a batch file output ONLY the short-name of folders and sub-folders to a file. However, with the example below I am only able to get the fullpath.
DIR /S /B /O:N /A:D > FolderList.txt
Which will output:
X:\Example\Folder 1
X:\Example\Folder 2
X:\Example\Folder 3
X:\Example\Folder 1\Sub-Folder 1
X:\Example\Folder 1\Sub-Folder 2
X:\Example\Folder 2\Sub-Folder 1
When the desired output is:
Folder 1
Folder 2
Folder 3
Folder 1\Sub-Folder 1
Folder 1\Sub-Folder 2
Folder 2\Sub-Folder 1
The issue comes with the /S switch that allows the DIR command to recurse into sub-folders.
Is there a simple way, using only a Windows Batch File, to output a list of folders and sub-folders in the current directory to a text file?
#ECHO OFF
FOR /f "delims=" %%a IN ('DIR /S /B /O:N /A:D') DO (
SET "name=%%a"
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO(!name:%cd%\=!
endlocal
)
GOTO :EOF
made a little more confusing because you ask for the "short name" then describe the "relative name".
Obviously, name simply echoed to screen. You're aware of how to redirect.
Just to include a solution using a recursive function call approach
#echo off
setlocal enableextensions disabledelayedexpansion
call :getSubFolderList "%~1"
goto :eof
:getSubFolderList folder [prefix]
for /d %%a in ("%~f1.\*") do for %%b in ("%~2%%~nxa") do (
echo %%~b
call :getSubFolderList "%%~fa" "%%~b\"
)
goto :eof
When called with a starting folder, it will iterate over the list of subfolders, and for each one the subroutine will call itself to handle the descending folders.
The other answers to this question using echo to output the folder path use delayedexpansion, echoing the content of the variable used without any problem caused by the parser. But the code in this answer does not use delayed expansion, and characters as &() in the folder names can be a problem in the echo command.
To avoid this problem, the value to echo is quoted and wrapped inside a for replaceable parameter. That is the reason for the for %%b in the code.
To generate a file with the list of folders, the only change needed is, in the first call command:
call :getSubFolderList "%~1" > fileList.txt
note: the code in the answer has been written to receive the folder to be processed as the first argument to the batch file. Change "%~1" to your needs.
This uses a little trick with the old SUBST command to make the root folder a drive letter. Then you can use the FOR command modifiers to drop the drive letter from the variable on output.
#echo off
SET "folders=X:\Example"
subst B: "%folders%"
B:
(FOR /F "delims=" %%G in ('DIR /S /B /O:N /A:D') do echo %%~pnxG)>"%~dp0folderlist.txt
subst B: /D
Now obviously this does not check to make sure that the drive letter B: is available before using it. Easy enough to add some code to check for a drive letter that is not in use before executing the SUBST command.
To confirm my comment with regard the duplicate response:
#Echo Off
SetLocal EnableDelayedExpansion
For /L %%A In (1 1 8192) Do If "!__CD__:~%%A,1!" NEq "" Set/A "Len=%%A+1"
SetLocal DisableDelayedExpansion
(For /D /R %%A In (*) Do (
Set "AbsPath=%%A"
SetLocal EnableDelayedExpansion
Echo(!AbsPath:~%Len%!
EndLocal))>FolderList.txt

Resources