I want to generate a file that contains the directory structure of a given directory, as relative paths. Currently I have the following batch file:
#echo off
pushd "C:\TEST"
dir /AD /B /ON /S
popd
Its current output is this:
C:\TEST\one
C:\TEST\three
C:\TEST\two
C:\TEST\one\a
C:\TEST\three\d
C:\TEST\three\e
C:\TEST\three\f
C:\TEST\two\b
C:\TEST\two\c
I want the output to be:
one
three
two
one\a
three\d
three\e
three\f
two\b
two\c
EDIT: this question is not a duplicate. The other question shows files exclusively, now I need to get directories exclusively (not mixed with files).
#echo OFF
SETLOCAL enabledelayedexpansion
SET "targetdir=c:\106x"
pushd "%targetdir%"
FOR /f "delims=" %%a IN ('dir /AD /B /ON /S') DO (SET "dirname=%%a"&ECHO(!dirname:%targetdir%\=!)
popd
GOTO :EOF
This should work for you provided the directoryname does not contain !
The directorynames are applied to %%a and transferred to dirname for manipulation. The target directoryname + a closing \ are then replaced by nothing for display.
Related
I tried using dir /b/s *.png to list the directories of all my png files. the results were like this:
D:\Newfolder\test\images\approved\11.png
D:\Newfolder\test\images\approved\12.png
D:\Newfolder\test\images\approved\13.png
D:\Newfolder\test\images\approved\14.png
D:\Newfolder\test\images\approved\15.png
D:\Newfolder\test\images\approved\16.png
D:\Newfolder\test\images\approved\17.png
D:\Newfolder\test\images\approved\18.png
D:\Newfolder\test\images\approved\19.png
D:\Newfolder\test\images\approved\20.png
I want it to be shortened so it will display only starting from the images folder;
images\approved\11.png
images\approved\12.png
images\approved\13.png
images\approved\14.png
images\approved\15.png
images\approved\16.png
images\approved\17.png
images\approved\18.png
images\approved\19.png
images\approved\20.png
is it possible to do?
if it's not, is there any way for me to edit the directories by deleting the first few folder from a generated text file?
say i put dir /b/s *.png > path.txt how do i edit the texts since the list got no whitespaces.
i'm still new to this so i'm not so familiar with much commands but this is as far as my understanding can do.
Assuming this comment in your question:
"I want it to be shortened so it will display only starting from the "images" folder;"
you always want from the images folder, and also assuming the images folder always exists in the path:
#echo off & setlocal enabledelayedexpansion
for /R %%i in (*.png) do (
set "_fp=%%~i"
echo !_fp:*\images\=images\!"
)
pause
Or to explicitly ensure you only include paths with \images\ in the path:
#echo off & setlocal enabledelayedexpansion
for /F "delims=" %%i in ('dir /b /s *.png ^| findstr \images\') do (
set "_fp=%%~i"
echo !_fp:*\images\=images\!"
)
pause
example of using pushd:
#echo off & setlocal enabledelayedexpansion
pushd "%~1"
for /F "delims=" %%i in ('dir /b /s *.png ^| findstr \images\') do (
set "_fp=%%~i"
echo !_fp:*\images\=images\!"
)
pause
popd
So the above you can run from cmd and simply pass the path you want the script to run in as script_name.cmd "C:\some path\here"
I'm trying to get the name and time of the oldest file in a folder (By modification date).
I can get the name without any problem using this code
for /f "delims=" %%x in ('dir /b /o-d /a-d %currentfolder% ^| grep -v / ') do (SET FILEINFO=%%x )
From my understanding swapping the %%x for %%~tx should return the modified time instead of the filename. But I get a blank instead.
for /f "delims=" %%x in ('dir /b /o-d /a-d %currentfolder% ^| grep -v / ') do (SET FILEINFO=%%~tx )
The following code returns the time of a file in the folder but not the oldest one.
for %%a in (%currentfolder%\*) do (set LAST_TIME=%%~ta)
I tried to combine the first and last code to get the time of the oldest file but it also returns a blank.
for %%b in (%currentfolder%\%FILEINFO%) do (set MAXDATE=%%~tb)
What is the error here ? How can I solve this ?
Thank you very much for the help
You are almost there:
#echo off
set "currentfolder=D:\some directory\"
pushd "%directory%"
for /f "delims=" %%i in ('dir /b /a-d /od') do (
set "file=%%i"
set "moddate=%%~ti"
goto :done
)
popd
:done
echo %file% %moddate%
So we sort by date (oldest first) then set the first filename as %file% and it's date to %moddate% then we exit the loop so it does not do the same for the other files in the folder.
The problem is caused by the fact that your current working directory referred to by for /F is not the same as the directory you are searching files in by dir.
This can be fixed like this (omitting grep as I do not understand its purpose here):
rem // Temporarily change to the directory containing the files of interest:
pushd "%currentfolder%"
rem /* The current working directory is now the target directory;
rem thus both `dir` and `for /F` work in the same directory: */
for /F "delims=" %%x in ('dir /B /A:-D /O:-D') do (set "FILEINFO=%%~tx")
rem // Restore the former working directory:
popd
rem // Just output the gathered information:
echo/%FILEINFO%
Alternatively, the pushd command line could be replaced by cd /D "%currentfolder%" when popd is removed, given that you do not need the original working directory to be restored.
To understand what was going on in your original code, let us assume:
the current working directory is C:\TEST;
the content of variable currentfolder is D:\DATA;
the directory C:\TEST contains nothing but the batch file;
the directory D:\DATA contains a file called some.txt;
The command line dir /b /o-d /a-d %currentfolder% returns only pure file names (due to its option /B), so based on the predefined sample data, the output would be:
some.txt
Now this text is captured by the for /F loop. Now the last modification date/time is queried by %%~tx, which of course requires access to the file system. Remember that the current working directory is C:\TEST, so the for /F loop tries to gather the information from the following file:
C:\TEST\some.txt
Since such a file does not exist, the output is blank.
To prove that, simply place a new file some.txt into the directory C:\TEST, then you would receive the last modification date/time of that file.
I'm trying to put together a Windows batch script that moves the most recent file to a different directory. Here's my batch script mostly stolen from here:
FOR /F "tokens=*" %%G IN ('dir /b *.*') DO move %%G C:\Users\jrobinson\Desktop\ & exit /b
When I run this it moves every file in the folder. Interestingly, when I replace the MOVE command with a COPY command, the script copies only one file:
FOR /F "tokens=*" %%G IN ('dir /b *.*') DO copy %%G C:\Users\jrobinson\Desktop\ & exit /b
REM ---------------------------------------^^^^
Why is the move script moving every file while the copy script is only copying one file? Is it possibly because my script file is also in that folder and because of my edits, it is the most recent file?
Edit: Here are the contents of my source folder:
myBatchFile.bat
newest.txt
oldest.txt
second.txt
Of the *.txt files, newest.txt has the most recent modified date. Of all of the files regardless of extension, myBatchFile.bat has the most recent modified date given that I keep making edits to it to try to get it to work.
Edit #2: Here's a screenshot of my command window after running the first command above. This shows that all of the files in my source folder are copied when I only expect the newest file to be copied.
I'd use dir /b /o:-d /a:-d *.*, so the items are sorted by date (newest first) and directories are excluded. Otherwise the sort order is not clear, and directories like . (current) or .. (parent) might be returned unintentionally.
Instead of %%G I recommend using "%%~fG" to provide the full path, surrounded by doublequotes. Also the destination path should be enclosed in "" to avoid troubles with whitespaces.
The FOR /F should be changed to "delims=" in case the file name starts with a space (which I think is valid in Windows). "tokens=*" removed them.
Furthermore, I'd put parenthesis () around the code after do (so it is guaranteed and obvious that both commands move and exit /b are part of the loop context).
So all in all this leads to the following code:
FOR /F "delims=" %%G IN ('dir /b /o:-d /a:-d *.*') DO (move "%%~fG" "C:\Users\jrobinson\Desktop\" & exit /b)
Since the newest file is enumerated first and the for body contains exit /b (exit batch file), only that file is moved.
If you need to execute some other code after this line, replace exit /b by goto :SKIP (or any other valid label), and state the label (:SKIP) immediately after the FOR command block.
If the batch script containing the code herein is located in its working directory, moving it (in case it is the newest file) most likely results in unexpected behaviour. You can exclude the batch script itself by filtering it out using find like this:
FOR /F "delims=" %%G IN ('dir /b /o:-d /a:-d *.* ^| find /v /i "%~nx0"') DO (move "%%~fG" "C:\Users\jrobinson\Desktop\" & exit /b)
%~nx0 therein expands to the file name and extension of this script (see call /?).
I'm not sure I believe what you say. Because when I type the same command, is a file that I see first followed by the PAUSE command (or exit)
FOR /F "tokens=*" %G IN ('dir /b *.*') DO #echo %G & pause
So it always goes first action on the first file and the script will stop.
See this 5 secs gifv: http://i.imgur.com/kyHdN1Y.gifv with the following code:
#echo off
if exist ..\destination-test-folder\nul rd /s /q ..\destination-test-folder
if not exist ..\destination-test-folder\nul md ..\destination-test-folder
copy nul newest.txt>nul
copy nul oldest.txt>nul
copy nul second.txt>nul
dir /b .
pause>nul
echo: &echo For loop command: &echo:
for /f "tokens=*" %%g in ('dir /b "*.*"') do if "%%g" neq "%~nx0" move %%g ..\destination-test-folder>nul & echo pause is stated after each iteration & echo 1 file(s) moved. &pause>nul
echo: &echo list destination:
dir /b "..\destination-test-folder" &echo: &echo list source: &echo:
dir /b .
Just wanted to say thanks person: aschipfl
You are my hero.
here is the command I used to move all read only files to a sub folder "temp"
md temp
FOR /F "delims=" %%G IN ('dir /b /o:-d /a:R *.*') DO (move "%%~fG" "temp" )
How can I test if a file is a symbolic link from a batch file (windows cmd.exe)?
(I would have thought that this was a well phrased question, but stackoverflow appears to want me to write some more, so here it is!)
dir %filename% | find "<SYMLINK>" && (
Do something
)
for /f "tokens=2delims=[]" %%a in ('dir /ad ^|find "<SYMLINKD>"') do echo Symlink: "%%a"
This doesn't work with [] in Symlink names.
Here is an even faster solution as it doesn't require a pipe and also allows access to the original file name either as a relative or absolute path:
#echo off
setlocal EnableDelayedExpansion
set ScriptPath=%~dp0
cd /d "%ScriptPath%"
set "r=%__CD__%"
set SearchTarget=SomePath
for /f "tokens=*" %%a in ('dir /s /b /a:l %SearchTarget% 2^>nul') do (
set "FullPath=%%a"
set "LocalPath=!:%r%=!"
rem local -> [absolute]
echo(!FullPath:%r%=! -^> [%%a]
)
If you don't want to search recursively then remove the /s option for the dir command.
This question might have a simple solution, but I just cannot find it.
Let's say I'm using the DIR command to produce a list of .txt files in the folder "E:\Documents". How can I make sure that only the .txt files one level below "E:\Documents" are listed (i.e. in a direct subfolder) and not the files in "E:\Documents" itself. "E:\Documents\\" or "E:\Documents\*\" doesn't seem to do the trick.
Thanks in advance!
FOR /f "delims=" %%i IN ('dir /b/ad') DO IF EXIST ".\%%i\*.txt" DIR ".\%%i\*.txt"
That's if you want the output in DIR format - with headers
FOR /f "delims=" %%i IN ('dir /b /ad') DO IF EXIST ".\%%i\*.txt" (
FOR /f "delims=" %%q IN ('DIR /b ".\%%i\*.txt" ') DO ECHO ".\%%i\%%q"
)
if you want just the filenames.
This can be achieved without dir:
for /d %%d in ("C:\basedir\*") do for %%f in ("%%~fd\*.txt") do echo %%~ff
If you need not only the file names, but also detail information about the files, add the respective qualifiers, e.g.:
for /d %%d in ("C:\basedir\*") do for %%f in ("%%~fd\*.txt") do echo %%~azff
a → attributes of the file
t → timestamp of the file
z → size of the file
See help for for details.