I have a data set consisting of files organised according to the following hierarchical folder/subfolder structure:
I would like to remove all nuisance subfolders (move its contents outside of it at the same hierarchical level + delete the nuisance folder), thus ending up with the files organised like this:
How can I achieve this, using a batch file, run from a command prompt inside Windows 7? I've tried a number of for statements with %F and %%F, but none worked. Grateful for any tips.
I believe the following will accomplish your goal if and only if all child folder and file names are unique. If there are duplicates, then all hell will break loose.
I have not tested, so backup and/or try the code on disposable data first.
You will have to modify the first PUSHD command to point to the root where all your "person n" folders reside.
#echo off
pushd "yourRootWherePersonFoldersReside"
for /d %%U in (*) do (
pushd "%%U"
for /f "eol=: delims=" %%A in ('dir /b /ad 2^>nul') do (
for /d %%B in ("%%A\*") do (
for /d %%C in ("%%B\*") do (
md "%%~nxC"
for /d %%D in ("%%C\*") do move "%%D\*" "%%~nxC" >nul 2>nul
)
)
rd /s /q "%%A"
)
popd
)
popd
The second FOR loop must be FOR /F instead of FOR /D because FOR /D has the potential to iterate folders that have been added after the loop has begun. FOR /F will cache the entire result of the DIR command before iteration begins, so the newly created folders are guaranteed not to interfere.
Related
I have the following file and folder structure (using real names):
Carabidae/Pterostichinae/FolderNameXXX/dor/StackXXX/files.tif
My problem is that I need to get one specific file, PM*.*, from the StackXXX folders into their respective /dor parent folders. The StackXXX folder can then be deleted.
There are hundreds of FolderName. Ideally I would like a batch file I can run from the Carabidae folder.
This needs to be a batch file because there will be new FolderNames added constantly.
After a lot of searching, I found a semi-working solution from this StackOverflow answer:
for /f "delims==" %%i in ('dir /a:d /b') do for /f "delims==" %%f in ('dir %%i /a:d /b') do (move "%%i\%%f\PM*.*" "%%i"&&rd "%%i\%%f" /s /q)
It moves the file and deletes the folder, just as I want. But the problem is that it only works when run from a FolderName folder, which defeats the time-saving purpose of the script. I don't know how to modify it to recurse into subfolders so I can run it from the top folder.
Thank you very much for any help!
#ECHO OFF
SETLOCAL
SET "sourcedir=u:\Carabidae"
FOR /f "tokens=1*delims=" %%a IN (
'dir /b /s /a-d "%sourcedir%\pm*.*" '
) DO IF EXIST "%%a" (
FOR %%p IN ("%%~dpa..\.") DO IF /i "%%~nxp"=="dor" (
ECHO %%a|FINDSTR /i "\\dor\\Stack" >NUL
IF NOT ERRORLEVEL 1 (
ECHO MOVE /y "%%~dpa\pm*.*" "%%~dpa..\"
ECHO RD /s /q "%%~dpa"
)
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
Find all of the pm*.* files, filenames to %%a
Ensure the parent directory is dor and ensure that \dor\stack\ is in the path. If so, move the file(s) and remove the directory.
The if exist gate ensure no hiccoughs if a target directory contains more than one pm*.* file.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
The required RD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(RD to RD to actually delete the directories.
Add >nul at the end of the move command to suppress the move-report if required.
As usual, I'd suggest you test against a representative subtree first.
Here is a possible solution, given that only the XXX parts in your path sample are variable:
rem // Enumerate `FolderName*` directories:
for /D %%R in ("Carabidae\Pterostichinae\FolderName*") do (
rem // Enumerate `Stack*` sub-directories within `dor` sub-directories:
for /F "delims= eol=|" %%D in ('dir /B /A:D "%%~R\dor\Stack*"') do (
rem // Check for `PM*.*` files in `Stack*` sub-directories:
(
rem // Enumerate `PM*.*` files:
for /F "delims= eol=|" %%F in ('dir /B /A:-D "%%~R\dor\%%D\PM*.*"') do (
rem /* Move `PM*.*` file one directory level up, overwriting
rem an already existing file, if applicable: */
ECHO move /Y "%%~R\dor\%%D\%%F" "%%~R\dor\%%F"
)
) && (
rem /* Remove `Stack*` sub-directory after file movement;
rem this is skipped if no `PM*.*` files have been found in the `Stack*`
rem sub-directory, so when the `for /F %%F` loop did never iterate: */
ECHO rd /S /Q "%%~R\dor\%%D"
)
)
)
After having successfully tested whether or not the correct items are returned, remove the upper-case ECHO commands to actually move PM*.* files and remove Stack* directories!
I want to copy and rename files that are stored in a stack of directories (year, month, day). The files are .ers files and I need them to maintain their extension but to go from file.ers to file_cloud.ers.
Then I would like the files for a given month to be saved in the cloud folder within each month.
Ideally I would do this in the Windows Command Line.
I understand a batch file is a good place to start, and so I have the following - this doesn't include saving in a different location - but I am struggling with just the copy and rename.
for /D %%y in ("C:\Data\20*") do (
pushd "%%~y"
for /D %%m in ("*") do (
pushd "%%~m"
for /D %%d in ("*") do (
pushd "%%~d"
for %%f in (soig_*.ers) do copy "%%~f.ers" "%%~f_cloud.ers"
popd
)
popd
)
popd
)
This might be easier than you are making it. If this echos the correct copy command, remove the echo. You get this by sticking your head way down into the output of FOR /?.
FOR /F "usebackq tokens=*" %%f IN (`DIR /S /B /A:-D "*.ers"`) DO (
echo COPY "%%~f" "%%~dpnf_cloud.%%~xf"
)
The following should work okay for you, (it is supposed to copy all matching .ers files with updated names to the existing cloud directory at the previous level of their tree).
#FOR /D %%Y IN ("C:\Data\20*") DO #FOR /D %%M IN ("%%Y\*"
) DO #FOR /D %%D IN ("%%M\*") DO #IF /I NOT "%%~nxD"=="cloud" FOR %%F IN (
"%%~D\soig_*.ers") DO #COPY "%%F" "%%~M\cloud\%%~nFcloud%%~xF">NUL
I have not included anything to prevent overwrites of files whose names already exist within that cloud directory
I have a folder that contains subfolders with MP4 files. I'm trying to write a script that will move the MP4 files out of the subfolders into the root folder when ran. The batch file I wrote is working, but when the batch script runs again for new subfolders, the MP4 files that were already copied to the root folder, get moved up another level in the file structure. For example:
C:\MainRoot\Root\Subfolder\media.mp4
When script is ran, 'media.mp4' gets moved up to C:\Root\media.mp4 as desired.
But since I need the script to run on a scheduled task. The next time the script runs I get the following:
C:\MainRoot\media.mp4
Instead of just the MP4 file staying in C:\MainRoot\Root.
Here's my batch file so far to copy the mp4 files:
set root_folder=C:\MainRoot\Root
for /f "tokens=1* delims=" %%G in ('dir %root_folder% /b /o:-n /s ^| findstr /i ".mp4" ') do (
move /y "%%G" "%%~dpG..\%%~nxG"
)
What do I need to modify so that once moved, the MP4 files will stay in place?
Any help would be greatly appreciated!
Since all your source files seem to be at a certain directory level, a for /D loop could be wrapped around your for /F loop, which parses the output of a non-recursive dir command line (no /S):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=C:\MainRoot\Root"
set "_PATTERN=*.mp4"
rem // Loop through sub-directories:
for /D %%D in ("%_ROOT%\*") do (
rem // Loop through matching files:
for /F "eol=| delims=" %%F in ('dir /B "%%~fD\%_PATTERN%"') do (
rem // Avoid overwriting destination file:
if not exist "%_ROOT%\%%~nxF" (
rem // Move matching file one level up:
move /Y "%%~fD\%%~nxF" "%_ROOT%\%%~nxF"
)
)
)
endlocal
exit /B
If you are happy to overwrite as in your provided example then something as simple as this may suit your purpose:
#Echo Off
Set root_folder=C:\MainRoot\Root
If /I NOT "%CD%"=="%root_folder%" PushD "%root_folder%" 2>Nul||Exit/B
For /R %%G In (*.mp4) Do If /I NOT "%~dpG"=="%root_folder%\" Move "%%G">Nul 2>&1
If the files are only one folder deep you may prefer this:
#Echo Off
Set root_folder=C:\MainRoot\Root
If /I NOT "%CD%"=="%root_folder%" PushD "%root_folder%" 2>Nul||Exit/B
For /D %%G In (*) Do Move "%%G\*.mp4">Nul 2>&1
i've engaged with work in batch script.these things i need to do
1.i want to find the folder say like "name" in particular directory
ex:
c:\test\name
c:\test\b\name
c:\test\n\c\name
2.in the name folder, need to delete all sub folders and files and all which is more than 90 days.
i have changed my question now please give me an idea...
#ECHO OFF
SETLOCAL
SET "targetdir=U:\destdir"
ECHO(DEL "%targetdir%\*?*"
FOR /f "delims=" %%a IN (
'dir /b /ad "%targetdir%\*" '
) DO (
ECHO(RD /S /Q "%%~a"
)
GOTO :EOF
You would need to change the setting of targetdir to suit your circumstances. It could of course be replaced by a literal if you wish.
The required RD commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(RD to RD to actually delete the directories.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(DEL to DEL to actually delete the files.
the del and for commands could be cascaded with a & if required. The for is spread across a nuber of lines for clarity.
You're missing an asterisk * so that the folder set expands to all subdirectories of the _delete folder. Also, the /D /R construct seems unnecessary on second thought, because RD /S does already take care of deleting directories recursively.
FOR /D %%A IN ( folder_you_want_to_clean\* ) DO IF EXIST "%%A" RD /S /Q "%%A"
But it won't delete the files in the folder_you_want_to_clean folder itself, though. Do that with the DEL command - the /Q option suppresses the confirmation prompt, just like with the RD command:
DEL /Q folder_you_want_to_clean\*
Concrete example: Suppose the folder you want to clean is C:\data\oldstuff. Then just do:
FOR /D %%A IN ( C:\data\oldstuff\* ) DO IF EXIST "%%A" RD /S /Q "%%A"
All directories contained in C:\data\oldstuff will be gone (and of course, any files in those directories). But any files in C:\data\oldstuff itself will still be there! So to delete those as well, do:
DEL /Q C:\data\oldstuff\*
The code below moves all files under each movie folder into the appropriate movie folder, and if there are empty folders they'll be deleted.
Example:
Before:
D:\MOVIES
-----------\Bikini Spring Break
-------------------------------\EPCSKGCWZCXDJEH
------------------------------------------------------------\DVD
-----------------------------------------------------------------\P2HBSB5.iso
-----------------------------------------------------------------\0001.jpg
-----------------------------------------------------------------\lees.txt
After:
D:\MOVIES
------------\Bikini Spring Break
----------------------------------\P2HBSB5.iso
----------------------------------\0001.jpg
----------------------------------\lees.txt
#echo off
pushd "d:\MOVIES"
for /f "delims=" %%a in (' dir /ad /b ') do (
pushd "%%a"
for /r %%b in (*) do move /-y "%%b" .
for /f "delims=" %%c in (' dir /b /s /ad ^|sort /r') do rd "%%c" 2>nul
popd
)
popd
Is it possible to change something in the code from this batch command so only in selected folders the code is executed?
Maybe it's just a minor change if this batch command is placed into the "MOVIES" folder and executed from there.
Example:
If from these three movies only "Bikini Spring Break" and "Static" are selected in the "MOVIES" folder, I want only the code executed on these movies.
D:\MOVIES\Bikini Spring Break
---------------\Breaking the Girls
---------------\Static
This could work for you -
It uses drag and drop to process the folders that are selected.
Drag the folders onto the batch file.
What it doesn't do is check for filename clashes if any exist when moving the files recursively into a movie folder.
It is untested so make some copies of your folders and test it first.
#echo off
:loop
pushd "%~1"
for /r %%b in (*) do move "%%b" .
for /d %%c in (*) do rd /s /q "%%c"
popd
shift
if not "%~1"=="" goto :loop