Im trying to change the name of folders inside a folder to the name of the folders owner..
Exemple, I have a folder with one hundred other folder's all with the name "My Documents" and all of the with a diferente owner.
I already find a way to find the name with the code:
dir /q
but I have no ideia on how to put it in a variable and use that variable to change the folders name...
The usual way to get a commands output is a for.
#echo off
for /f "skip=2 tokens=4,*" %%a in ('dir /q /ad^|find "<DIR>"') do (
for /f "tokens=2 delims=\" %%i in ("%%a") do (
echo owner=%%i
echo folder=%%b
echo ren "%%b" "%%i"
)
)
Here is a batch script -- let us call it rename-dir-by-owner.bat -- based on the code in my comment:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "delims=" %%U in ('
dir /Q /A:D "%~1" ^| find "<DIR>" ^| findstr /V /R /C:" \.*\.$"
') do (
set "ITEM=%%U"
setlocal EnableDelayedExpansion
set "ITEM=!ITEM:*<DIR>=!" & set "ITEM=!ITEM:*\=!"
for /F "tokens=1,* delims= " %%O in ("!ITEM!") do (
endlocal
ECHO ren "%~dp1%%P" "%%O"
setlocal
)
endlocal
)
endlocal
exit /B
To use this script, provide the directory containing the ones subject to rename as a command line argument -- like this, for instance, supposing the directory is called parent-folder:
rename-dir-by-owner.bat "parent-folder"
The upper-case ECHO command is there for testing purposes; remove it as soon as you actually want to rename any items.
Explanation
The output of the core dir /Q /A:D command line used in the above script looks similar to this:
Volume in drive D has no label.
Volume Serial Number is XXXX-XXXX
Directory of D:\Data
2016/01/01 00:00 <DIR> NT AUTHORITY\SYSTEM .
2016/01/01 00:00 <DIR> BUILTIN\Administrators ..
2015/07/01 01:00 <JUNCTION> NT AUTHORITY\SYSTEM AppData [C:\Users\aschipfl\AppData\Roaming]
2016/03/21 20:00 <DIR> HOST\aschipfl Documents
2016/05/18 23:00 <DIR> HOST\aschipfl Drawings
2016/04/01 13:00 <DIR> HOST\aschipfl Projects
0 File(s) 0 bytes
6 Dir(s) 2'147'483'648 bytes free
The find command filters out all lines that do not contain <DIR> (which marks directories), findstr removes the dummy directories . (current) and .. (parent). So the following lines remain:
2016/03/21 20:00 <DIR> HOST\aschipfl Documents
2016/05/18 23:00 <DIR> HOST\aschipfl Drawings
2016/04/01 13:00 <DIR> HOST\aschipfl Projects
These lines are captured by the outer for /F loop, each one is stored in variable ITEM. Afterwards everything up to the portion <DIR> is removed, then everything up to the (first) \ is cut off. The remaining content of ITEM is now parsed with another for /F loop, which extracts everything in front of the first white-spaces, so the user name of the owner is retrieved; behind the white-spaces is the directory name. Both string parts are passed over to the ren command finally (once ECHO is away).
With this approach the result does (almost) not depend on the locale and region settings of the system, so a quite general solution is achieved. However, this batch program leads to unexpected results if a user name contains white-spaces, but such is not recommended by Microsoft anyway -- consult this article: Creating User and Group Accounts, section "Rules for Logon Names".
Related
I have never tried this, and I have been searching to see the best way to make a script that can extract content from a txt file into their own txt files
Now I managed this and it extracts all content into their own txt files, but not sure how to make it use the extracted content as the txt filename
#echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in ('type "a.txt"') do (
cd > %%a.txt
)
endlocal
so I have this
Content of my a.txt:
All_type_2020
All_Foods_2021
and this is what I get
All_type_2020All_Foods_2021.txt
I have tested many different scripts, and the closes I have gotten was with the script above
my goal is to have this results
All_type_2020.txt
All_Foods_2021.txt
I'm not entirely sure of what it is you're seeking, however I might have something that nevertheless might help you.
The code I wrote below will check for each sentence in "a.txt" if the first word is equal to "blue" if so it will output it into a txt file.
for /f "delims=" %%a in (a.txt) do if "%%a" == "blue" (
echo - %%a is blue >blue.txt
) else (
if "%%a" == "red" echo - %%a is red >red.txt)
pause
This is an oversimplified version of what I think you're trying to do, but hopefully it can help. To change how the document filters look around the website and you will surely find ways for it to help.
So, contents of a.txt
All_type_2020
All_Foods_2021
All_type_2021
All_Foods_2022
All_type_2022
Contents of my CMD file:
#echo off
for /f "delims=*" %%a in (a.txt) do (
echo. >%%a.txt
)
In the directory, I then have these empty files:
11/10/2022 10:22 AM <DIR> .
11/10/2022 10:22 AM <DIR> ..
11/10/2022 10:22 AM 77 a.txt
11/10/2022 10:22 AM 3 All_Foods_2021.txt
11/10/2022 10:22 AM 3 All_Foods_2022.txt
11/10/2022 10:22 AM 3 All_type_2020.txt
11/10/2022 10:22 AM 3 All_type_2021.txt
11/10/2022 10:22 AM 3 All_type_2022.txt
6 File(s) 92 bytes
Thanks to thecarpy and Pedro I was able to figure out my mistake
Here is the correct script
#echo off
setlocal enabledelayedexpansion
for /f "delims=*" %%a in ('type "a.txt"') do (
cd. > %%a.txt
)
endlocal
This is the contents of a.txt
CONTENTS
All_type_2020
All_Foods_2021
All_type_2021
All_Foods_2022
All_type_2022
The Results
All_type_2020.txt
All_Foods_2021.txt
All_type_2021.txt
All_Foods_2022.txt
All_type_2022.txt
Both of these will do the job
#For /F UseBackQ^ Tokens^=*^ EOL^= %%G In ("a.txt") Do #CD.>"%%~G.txt"
How do I add the time to this batch file when I rename the file?
The results look like this but need time also: Daily Report_Wed 08222018.pdf
#echo off
Pushd c:\Temp
pdftk *.pdf cat output %fn%.pdf
ren %fn%.pdf %fn%.xxx
del *.pdf
ren %fn%.xxx "Daily Report".pdf
for /f "tokens=1-3 delims=/" %%a in ('echo %date%') do set today=%%a%%b%%c
for %%f in (*.pdf) do ren "%%f" "%%~nf_%today%%%~xf"
mkdir "Daily Reports for Review"
move *.pdf "Daily Reports for Review"
Here's something that could get you close to what you want (I modified your 1st for loop):
e:\Work\Dev\StackOverflow>echo Date: [%date%], Time: [%time%]
Date: [2018-08-22], Time: [22:51:36.23]
e:\Work\Dev\StackOverflow>for /f "tokens=1-6 delims=/-:., " %a in ('echo %date: =0%-%time: =0%') do (echo set now=%a%b%c%d%e%f)
e:\Work\Dev\StackOverflow>(echo set now=20180822225136 )
set now=20180822225136
Notes:
Since I am directly in cmd window, and you're in a batch file you have to double the percent sign (%) for parameters (%a -> %%a, %b -> %%b, ... like you already have in your snippet). For more details, check [SS64]: Double %% symbols why are they needed in a batch file?
As you probably noticed (most likely due to "Regional settings"), my date format differs than yours (that's why I added the hyphen (-) in the delims list; also the items ordering is reversed), so you might get slightly different behaviors on different computers (things will get even worse on non English locales, as #Stephan noticed), so it's not a reliable solution (I guess this is batch processing generic)
Here's an untested example for you which uses WMIC to retrieve non locale dependent date and time values:
#Echo Off
If Exist "C:\Temp\*.pdf" (CD /D "C:\Temp") Else Exit /B
Rem The values below can be modified according to your language or preferred day names
Set "WeekDays=Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
For /F %%A In ('WMIC Path Win32_LocalTime Get /Value^|FindStr "[0-9]$"') Do Set "%%A"
For /F "Tokens=1%DayOfWeek%" %%A In (". . . . . . . . . %WeekDays%") Do Set "DayName=%%A"
For %%A In (Day Hour Minute Month Second) Do Call Set "%%A=0%%%%A%%" & Call Set "%%A=%%%%A:~-2%%"
Rem Choose the output %FileName% you want from the following variables:
Rem %Year% e.g. 2018
Rem %Quarter% e.g. 3
Rem %Month% e.g. 08
Rem %WeekInMonth% e.g. 4
Rem %Day% e.g. 22
Rem %DayOfWeek% as an integer where Monday from %WeekDays% is 1 e.g. 3
Rem %DayName% as a string taken from %WeekDays% e.g. Wednesday
Rem %Hour% in 24 hr format e.g. 21
Rem %Minute% e.g. 57
Rem %Second% e.g. 53
Set "FileName=%DayName% %Month%%Day%%Year%%Hour%%Minute%%Second%"
Rem Choose the full or relative output directory name
Set "DirName=Daily Reports for Review"
If Not Exist "%DirName%\" MD "%DirName%"
PDFTK *.pdf cat output "%DirName%\%FileName%.pdf" && Del /Q *.pdf
You will need to include the full or relative path to PDFTK on the last line if it is not located in the current working directory, (C:\Temp), or in %PATH%. Other than that, you should only make modifications to values on lines beginning with Set.
Empty lines and those Remarked can be optionally removed once you've made your modifications.
I need to search a remote directory (psexec), then store the result in a variable.
I have a directory that is filled with many other folders each containing some files I need to execute. Each computer on the network has the files I need are in different directories.
For example, I would search (using psexec) with
dir *Google_Chrome_49_0_2623_112_X64_EN_R01* /s
And I would get the result
Volume in drive C is OSDISK
Volume Serial Number is C8AD-F658
Directory of C:\Windows\ccmcache\2a
12/04/2016 01:52 PM 458 Google_Chrome_49_0_2623_112_X64_EN_R01.cab
14/04/2016 05:26 PM 69,632 Google_Chrome_49_0_2623_112_X64_EN_R01.mst
2 File(s) 70,090 bytes
Total Files Listed:
2 File(s) 70,090 bytes
0 Dir(s) 4,726,218,752 bytes free
Now I need the same batch file to cd into the directory 2a and execute a script inside.
Is there any way to store '2a' in a variable so I can cd into it?
Currently I am doing this in 2 steps, where the batch will show me the search results, then prompt for the directory:
psexec \\%PCNAME% cmd /c (cd ..\ccmcache ^& dir *Google_Chrome_49_0_2623_112_X64_EN_R01* /s)
SET DIRECTORY=%1
SET /P DIRECTORY=Enter Directory:
Problem is, I need this to be fully automated. How can I do this?
Note: I've looked at several other threads, and none of the answers seem to help me. Seemingly the results from psexec don't flow back to the local interface.
I've tried:
for /f %%a in (psexec \\%PCNAME% cmd /c (cd ..\ccmcache ^& dir *Google_Chrome_49_0_2623_112* /s ^| FIND "Directory of C:\Windows\ccmcache\") DO (
SET v=%%a
)
to try to set the entire result line to a var, but when I check the var, it's empty.
I just discovered that you can map to a network share with pushd and run the search there instead of dealing with psexec until you need it.
So my code now looks like:
pushd \\%PCNAME%\C$\Windows\ccmcache
for /f "tokens=3" %%a in ('dir *Google_Chrome_49_0_2623_112* /s ^| FIND "Directory"') DO (
set v=%%a
for /f "tokens=4 delims=\" %%m in ('echo !v!') do (set x=%%m)
)
popd
Where %x% is now the directory I'm searching for.
I have these folders name inside directory A:
Veep
Vegas
Valentina
Valeria Medico Legale
I have this file list in the same directory A also
Veep - Season 1 BDMux
Valentina S01e01-13
Vegas S01e01-21
Valeria Medico Legale S01-02e01-16
For example
Veep [folder]
Veep - Season 1 BDMux [file]
veep is identical word for folder and file name.
I want to move this file
Veep - Season 1 BDMux
inside this folder
Veep
using a file .bat
Any help?
The simplest solution I can think of would be using string substituition. Note that it might not do what you want if you have directories with matching substrings like:
Veep
Veeponic
Although it's not a perfect solution, and very costly if there are many directories, it might give you a start.
It receives the directory you want to proccess as parameter %1:
#echo off
setlocal enabledelayedexpansion
pushd %1
for /F "USEBACKQ tokens=*" %%a in (`dir /b /a:-d`) do (
set "_file=%%a"
for /D %%b in (*) do (
if NOT "x!_file:%%b=!" == "x!_file!" (
echo moving "%%a" to %%b
)
)
)
popd
Save it as, let's say, my_batch.bat and, assuming your files/folders are in C:\songs\, call it from cmd with my_batch C:\songs\. The output will be
moving Valentina S01e01-13 to Valentina
moving Valeria Medico Legale S01-02e01-16 to Valeria
... and so on
Replace the echo line with the proper move command, e.g move "%%a" %%b
Edit: it should NOT work for directories with spaces in their names.
been doing research all day and I probably could have done this manually but I just want to learn how to do it to expand my knowledge
REQUIREMENTS:
I have a folder with 11xxx subfolders, I need to know when the oldest file within each of these subfolders was last modified
so far I tried to use the dir command to get a list of all folders and the last modified date of each of the files within a folder
echo Starting...
#echo off
if exist files.txt (del files.txt)
dir /on /s /tw /a-d | find /v "<DIR> ." | find /v "File(s)" > files.txt
if exist files1.txt (del files1.txt)
For /F "delims=" %%A in (files.txt) Do Echo %%A >> files1.txt
if exist files2.txt (del files2.txt)
For /F "skip=2 delims=*" %%A in (files1.txt) Do Echo %%A >> files2.txt
#echo on
echo Finishing...
del files.txt
del files1.txt
ren files2.txt files.txt
quit
ok so the above gave me a txt file in this format
Directory of C:\TEMP
2013/12/05 05:30 PM 22,528 6N85.mst
2011/06/21 12:01 PM 14,108,096 CitrixOnlinePluginWeb.exe
2014/02/19 01:59 PM 448 extract.cmd
2014/02/19 03:42 PM 0 files.txt
2011/08/04 08:41 AM 216 GLF1C8.tmp
2011/08/04 08:41 AM 2,630 GLF1C9.tmp
2011/08/04 08:41 AM 54 GLF1CA.tmp
2011/08/04 08:41 AM 64 GLF1CB.tmp
2011/07/05 12:29 PM 239,174 ITMURebootMSG.EXE
2013/11/28 04:20 PM 2,434,048 msxml.msi
2013/11/28 12:59 PM 2,066,376 msxml4-KB2758694-enu.exe
2004/04/15 10:10 AM 79 process.bat
2012/08/02 12:43 AM 4,594 process.log
2003/11/04 10:17 AM 376 procs.vbs
2014/02/18 03:32 AM 16,391 WakeUpAgt.LO_
2014/02/19 12:04 PM 9,247 WakeUpAgt.LOG
2005/03/09 09:40 AM 4,630,256 WindowsXP-KB895200-x86-ENU.exe
2005/10/12 02:06 PM 4,934,896 WINDOWSXP-KB902400-X86-ENU.exe
2006/05/25 12:12 PM 1,307,376 WindowsXP-KB913580-x86-ENU.exe
Total Files Listed:
0 Dir(s) 81,741,336,576 bytes free
I opened the txt file within excel to get the first 10 chars of each line to get the date in col A,
IMO this approach is wrong, maybe I should be doing it in a different way, anyone care to help?
You're on the right track. The built-in dir command, as you found, can do your sorting for you. If you only care about the date of the oldest file, let it sort by date modified (descending) and get the last entry in the list. This should do what you're after, I think:
for /f %%x in ('dir /b /o-d /a-d') do set OLDESTFILE=%%~fx last modified at %%~tx
echo %OLDESTFILE%
Let me break this down.
The switches to the dir command will give you a list of files only (/a-d), in "brief" form (/b - just a list of files, not the typical full dir output), and will sort that list by date, descending (/o-d).
The for loop that wraps around that iterates over each of these files and sets an environment variable to the text in the format:
C:\TEMP\WindowsXP-KB913580-x86-END.exe last modified at 2006/05/25 12:12 PM
You can read for /? for all of the gritty details about the other ~ modifiers you can use.
If you run this with echo on, you'll see that it actually sets this environment variable each time through the loop, overwriting it with each subsequent iteration. That's ok by us, though, since we only really want the last entry anyway.
Now, if you really only want the date and not the time, that's slightly trickier. You'll need to use a slightly uglier loop like this:
for /f %%x in ('dir /b /o-d /a-d') do (
for /f "tokens=1" %%a in ("%%~tx") do (
set OLDESTFILE=%%~fx last modified on %%a
)
)
echo %OLDESTFILE%
The inner for loop here takes the date and time (e.g., 2006/05/24 12:12) as a list of arguments. Since cmd uses spaces as delimiters by default, this gives you two tokens, 2006/05/24 and 12:12. By specifying tokens=1 you explicitly tell for that you only care about the first of those: the date*.
Hope this gets you going on the right track. Now that you have the tricky part, you can wrap all of this in a loop that gets you the list of directories you care to run this in.
*Pedantically speaking, you don't actually need the tokens=1 there, since %%a would only refer to the first token anyway, and the time would be in %%b, but I thought it would be useful for illustrative purposes.
first of all, thank you #Mark for helping me understand the for loops in dos, I was having trouble with them yesterday and I just couldn't figure out how they worked but now I think I understand!
one of the problems I found with %%~tx was that it didn't extract the last modified date, only the last accessed date, maybe I'm wrong but I figured I'd try a different approach anwyay
::delete any files called list.txt if they exist
if exist list.txt (del list.txt)
::loop through all directories including sub-directories
for /d /r %%x in (*) do (
if exist listTemp1.txt (del listTemp1.txt)
::loop through each file within directory, show time last written, sort desc
for /f "delims=" %%y in ('dir "%%x" /tw /o-d') do (
::append listTemp1.txt with list of files
echo %%y >> listTemp1.txt
)
if exist listTemp2.txt (del listTemp2.txt)
::append listTemp2.txt with lines containing / in the dates
find "/" listTemp1.txt >> listTemp2.txt
::loop through listTemp2.txt to get last line of file, no delims as the first space is after date and we only need date, set var OLDFile with date and current folder
for /f %%z in (listTemp2.txt) do set OLDFile=%%z %%x
::append list.txt with OLDFile
call echo %%OLDFile%% >> list.txt
)
if exist listTemp1.txt (del listTemp1.txt)
if exist listTemp2.txt (del listTemp2.txt)
the above script gave me the exact result I wanted, which was <date of oldest file within folder> <folder>
2014/02/20 C:\TEMP\folder 1
2014/02/19 C:\TEMP\folder 2
2014/02/19 C:\TEMP\folder 1\folder 2
I created temporary txt files since I couldn't pipe for loop results (possible?)
anyways, thanks again #Mark, couldn't have figured out how to do this without your help examples and most importantly the break down which helped me understand the code!