Create List of file for a directory - batch-file

I have a directory of files for example:
\1.gif
\1.pdf
\1.doc
\2.gif
\2.pdf
\2.doc
\3.gif
\4.gif
How do I get a file with just the list of files (with extensions) that have unique filenames? (i.e. 3.gif, 4.gif)
Thanks

This does not work with special characters like !, = and more.
#ECHO OFF &SETLOCAL
for %%a in (*) do set ".%%~na=%%~xa"& set /a $%%~na+=1
for /f "tokens=1*delims==." %%a in ('set .') do for /f "tokens=2delims==" %%c in ('set "$%%a"') do if %%c==1 echo(%%a.%%b

i havent tested it, but try this:
#echo off
setlocal enabledelayedexpansion
pushd path\to\dir
for /f %%i in ('dir /b *.gif') do (
find "%%~ni" "%tmp%\u" >nul 2>&1 || echo %%~ni >> "%tmp%\u"
)
for /f %%i in ('type "%tmp%\u"') do (
set inc=
for /f %%j in ('dir %%i.gif /b') do set /a inc+=1
if !inc! EQU 1 (dir /b %%i.* ^|find "log" /v >> log)
)
please feel free to comment if there are any mistakes, not in a position to test it right now.

This will work as long as none of the file names contain the = character:
#echo off
setlocal
for /f "eol== delims==" %%V in ('"set _ 2>nul"') do set "%%V="
for %%F in (*) do if not defined _%%~nF (set "_%%~nF=%%F") else set "_%%~nF=="
for /f "eol== tokens=2 delims==" %%F in ('"set _|findstr /v =="') do #echo %%F
EDIT
If you want to restrict output to only one file type, .gif for example, then all you need is an extra FINDSTR:
#echo off
setlocal
for /f "eol== delims==" %%V in ('"set _ 2>nul"') do set "%%V="
for %%F in (*) do if not defined _%%~nF (set "_%%~nF=%%F") else set "_%%~nF=="
for /f "eol== tokens=2 delims==" %%F in ('"set _|findstr /v ==|findstr /lie .gif"') do #echo %%F

Related

Specific use of double loop

I recently asked you guys some help for a double conditions in batch file. You guys helped me very well but I'm now struggling with a new trouble... I'm trying to optimize my script.
Previous question (How to double conditions in batch file?)
I would like to list all files with the .doc extension that are in the subfolders named on the current date only. I think I'm making a mistake on the use of this double loop.
#echo off
chcp 1252
set Pathname="D:\testDir"
set year=%date:~-4%
set month=%date:~-7,2%
set day=%date:~-10,2%
set logfile=%Pathname%\logs\log.txt
cd %Pathname%
d:
for /D /R %%i in (*%year%_%month%_%day%*) do (
for /R %%i %%s in (*.doc) do (
echo "file : %%s worked and does an output at %time%" >> %logfile%
)
)
Can you give me a little help? Thanks for your help and advices.
EDIT: I need to perform actions on each .doc file in folders containing the string YEAR_MONTH_DAY. But the .doc files can also be located in other subdirectories.
It could be something like that :
D:\testDir\directory1_2021_11_16\test.doc
D:\testDir\directory1_2021_11_16\test.log
D:\testDir\directory1_2021_11_16\subDirectory1\test.doc
D:\testDir\directory1_2021_11_16\subDirectory1\test.log
D:\testDir\directory1_2021_11_17\test.doc
D:\testDir\directory1_2021_11_17\test.log
D:\testDir\directory1_2021_11_17\subDirectory1\test.doc
D:\testDir\directory1_2021_11_17\subDirectory1\test.log
D:\testDir\directory1_2021_11_17\subDirectory2\test.doc
D:\testDir\directory1_2021_11_17\subDirectory2\test.log
D:\testDir\directory1_2021_11_17\subDirectory2\subSubDirectory1\test.doc
D:\testDir\directory1_2021_11_17\subDirectory2\ubSubDirectory1\test.log
D:\testDir\directoryThatIDontCare\test.doc
D:\testDir\directoryThatIDontCare\test.log
D:\testDir\directoryThatIDontCare\subDirectory1\test.doc
D:\testDir\directoryThatIDontCare\subDirectory1\test.log
Any solutions ? Thanks for your time guys !
Here's an example script you can learn from, and run, to achieve what your submitted code was intending to do.
#Echo Off
SetLocal EnableExtensions
Set "CurDate="
For /F "Delims==" %%G In ('"(Set _) 2>NUL"') Do Set "%%G="
For /F "Delims=" %%G In ('%SystemRoot%\System32\wbem\WMIC.exe Path
Win32_LocalTime Get Day^, Month^, Year /Format:List
2^>NUL') Do For /F "Tokens=*" %%H In ("%%G") Do Set /A "_%%G + 10000"
For /F "Tokens=1,* Delims==" %%G In ('"(Set _) 2>NUL"') Do (
SetLocal EnableDelayedExpansion & If %%H Gtr 10059 (For %%I In (!%%G:~-4!
) Do EndLocal & Set "%%G=%%I") Else For %%I In (!%%G:~-2!
) Do EndLocal & Set "%%G=%%I")
Set CurDate=%_Year%_%_Month%_%_Day%
For /F "Delims==" %%G In ('"(Set _) 2>NUL"') Do Set "%%G="
If Not Defined CurDate GoTo :EOF
Set "BaseLocation=D:\testDir"
PushD "%BaseLocation%" 2>NUL || GoTo :EOF
Dir "logs" /B /A:D 1>NUL 2>&1 || (MD "logs\%CurDate%" 2>NUL || GoTo :EOF)
Set "LogFile=%BaseLocation%\logs\log.txt"
For /F "EOL=? Delims=" %%G In ('Dir "*_%CurDate%" /B /A:D 2^>NUL'
) Do For /F Delims^= %%H In ('Set "PATHEXT^=" ^& %SystemRoot%\System32\where.exe
/F /R "%%G" "test.doc" 2^>NUL'
) Do (Echo file : %%~H worked and does an output at %TIME%) 1>>"%LogFile%"
If you want to know how any of it works, please use the built-in help information for each command, use the site search facility and/or your chosen search provider. I am not a private tutor, so will not be performing such a role.

Opening a random folder from a set directory

How can I create a batch script that opens a random folder within a specific directory? This code here prints out a randomly chosen file(I need it to open the folder, not the file) but I could not figure out how to open it.
#Echo Off
:Start
set directory="D:\Movies"
set count=0
for /f %%f in ('dir "%directory%" /b /s') do set /a count+=1
set /a randN=%random% %% %count% +1
set listN=0
for /f "tokens=1* delims=:" %%I in ('dir "%directory%" /a-d /b /s^| findstr /n /r . ^| findstr /b "%randN%"') do set filename=%%J
:Found
echo %filename%
pause
goto Start
I suddenly realised what I was doing wrong and solved the problem. Here is the final and working code:
#Echo Off
:Start
set directory="D:\Film"
set count=0
for /f %%f in ('dir "%directory%" /ad /b /s') do set /a count+=1
set /a randN=%random% %% %count% +1
set listN=0
for /f "tokens=1* delims=:" %%I in ('dir "%directory%" /ad /b /s^| findstr /n /r . ^| findstr /b "%randN%"') do set filename=%%J
:Found
%SystemRoot%\explorer.exe %filename%
exit /b
goto Start
You really shouldn't need to increment a count and use findstr for such a task; just assigning and sorting a random number should do:
#Echo Off
Set "source=D:\Film"
SetLocal EnableDelayedExpansion
For /D %%A In ("%source%\*") Do Set "$[!RANDOM!]=%%A"
For /F "Tokens=1* Delims==" %%A In ('"Set $[ 2>Nul|Sort"'
) Do Set "target=%%B" & GoTo Found
Exit /B
:Found
Explorer "%target%"
If you wanted a recursive directory search then change line 5 to:
For /D /R "%source%" %%A In (*) Do Set "$[!RANDOM!]=%%A"

IN ECHO statement how can i print all the columns without defining multiple output parameters

for /f " tokens=%i%-%j% delims=," %%a in (%input%) DO (
(ECHO %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j)>>%output%
)
"delims=" will force no delimiter and use full string making each line %%a instead of each word, delimited by ,.
for /f "delims=" %%a in (%input%) DO ECHO %%a >>%output%
If you would like to get rid of the , simply replace it.
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (%input%) DO ( set string=%%a
set string=!string: =,!
ECHO !string! >> %output%
)
endlocal
According to your comments, the following should do exactly, what you want: multiple spaces are reduced to one delimiter, no delimiters at the end of a line.
#echo off
setlocal enabledelayedexpansion
(for /f "delims=" %%a in (input.txt) do (
set "new="
for %%b in (%%a) do (
set "new=!new!,%%b"
)
echo !new:~1!
))>output.txt
Because your ? characters may be problematic with some solutions, the following may do what you require:
#Echo Off
Set "input=input.txt"
Set "output=output.txt"
Set "_="
(For /F "UseBackQ Delims=" %%A In ("%input%"
) Do Set "_="&Call :Sub %%A&Call Echo(%%_:~1%%)>"%output%"
If Not Defined _ Del "%output%"
Exit /B
:Sub
If "%1"=="" GoTo :EOF
Set "_=%_%,%1"
Shift&GoTo :Sub

Batch file that renames files numerically not working

I have a folder into which I do a print to file option and it saves my print job as a pcl file. The software I use to do the print to file names each file in following manner: GUID.XX.pcl where XX is a number.
Example:
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.6.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.7.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.8.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.9.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.10.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.11.pcl
What I want to do is rename the files so that they look like this:
1.pcl
2.pcl
3.pcl
and so on.
Here is the batch I use:
for %%a in (*.pcl) do (
set /a i+=1
ren "%%a" "!i!.new"
)
ren *.new *.pcl
This works but the problem is,in the example I gave above
It renames
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.10.pcl to 1.pcl
and
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.6.pcl to 3.pcl
I need it to rename
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.6.pcl to 1.pcl
and
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.10.pcl to 5.pcl
It is basically seeing 10 before 6. Is there some way around this?
for /F "tokens=1-3 delims=." %%a in ('dir /B *.pcl') do (
set /A num=100+%%b
set "name[!num:~1!]=%%a.%%b.%%c"
)
for /F "tokens=2 delims==" %%a in ('set name[') do (
set /A i+=1
ren "%%a" "!i!.pcl"
)
If you want to use two digits in the new name, so the order be preserved in dir or for listings, modify the second part this way:
set i=100
for /F "tokens=2 delims==" %%a in ('set name[') do (
set /A i+=1
ren "%%a" "!i:~1!.pcl"
)
EDIT: I tested my code and it works correctly. This is the output of the test session:
C:\> dir /b
test.bat
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.10.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.11.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.6.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.7.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.8.pcl
{2E594442-FDF9-4992-88DA-EA4ED2811ECD}.9.pcl
C:\> test
C:\> dir /b
1.pcl
2.pcl
3.pcl
4.pcl
5.pcl
6.pcl
test.bat
C:\> type test.bat
#echo off
setlocal EnableDelayedExpansion
for /F "tokens=1-3 delims=." %%a in ('dir /B *.pcl') do (
set /A num=100+%%b
set "name[!num:~1!]=%%a.%%b.%%c"
)
for /F "tokens=2 delims==" %%a in ('set name[') do (
set /A i+=1
ren "%%a" "!i!.pcl"
)
not tested:
for %%a in (*.pcl) do (
for /f "tokens=2 delims=}" %%# in ("%%~nxa") do (
ren "%%~fa" "%%#"
)
)

file exists with condition today's date

I have a folder where files are dumped with timestamps...
filename_ver20130405121320.csv
I wish to create a batch script that makes sure 5 files have been created with todays date.
im guessing i will need to use a for loop with a date limit of today.
FOR /r %foldername% %%g IN (*.csv) DO (
echo %%~nxg
)
using a forfiles statement lists the files, is it possible to use a counter and +=1 every time it displays a filename?
forfiles /S /P %foldername% /m *.csv /d 0
the logic is
if number of files in a foldername is less than 5 where file created is today
echo error! missing files
any help would be much appreciated
date returned on machine as Mon 22/07/2013
use this to set date
:: set date
FOR /F "TOKENS=1* DELIMS= " %%A IN ('DATE/T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN ('echo %CDATE%') DO SET mm=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN ('echo %CDATE%') DO SET yyyy=%%B
SET setDate=%dd%/%mm%/%yyyy%
#ECHO OFF
SETLOCAL enabledelayedexpansion
SET yyyy=2013
SET mm=07
SET dd=22
SET count=0
FOR /f %%g IN ('dir /b /a-d *%yyyy%%mm%%dd%????.csv') DO (
SET filename=%%~ng
SET filename=!filename:~-12,-4!
if "!filename!"=="%yyyy%%mm%%dd%" SET /a count+=1
)
ECHO %count%
GOTO :EOF
I've simply set yyyy,mm,dd to constants, obviously - just poke your date-decoder in as appropriate.
Note that you could prefix the filemask with a directoryname if required - and enclose the entire filemask in "rabbit's ears" if there are spaces or other confounding characters in the resultant mask.
Important: the filemask is merely a primary filter. The dir would list a file named filename_ver2013040512132.csv for instance (1 digit missing...) so the gymnastics with the processing would still be required.
I'm also assuming relatively sane filenames. Likely ! in a filename would cause conniptions.
I came up with this and it seems to work so far
for /f "tokens=2" %%I in ("%date%") do set today=%%I
for /f "tokens=5" %%G in ('dir %foldername% /a-d ^| find "%today%"') do (
set /a fileCounter += 1
echo %%G
)
echo %fileCounter%
This may work (untested): edited to check only the date in yyyymmdd format
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set datestamp=%dt:~0,8%
for /f %%a in ('dir "*ver%datestamp%*.csv" /b /a-d^|find /c /v "" ') do (
if %%a LSS 5 echo files are missing
)

Resources