2

I am looking for help with a batch script which can help me remove specific subfolders from all directories that are in the same place as the batch file. But instead of deleting everything in the subdirectory, I want to move the contents outside of the subdirectory first.

To elaborate, I receive files which are always nested inside folders with a very specific pattern:

  • Every request I receive is in a uniquely named folder which follows no specific pattern (the Job Folder).
  • Inside every Job Folder, there are two things:
    1. A folder denoting the language the file is in (Lang Folder).
    2. An xml file named "Manifest.xml" which contains instructions and metadata.
  • There is a folder inside every Lang Folder denoting the brand of the file (Brand Folder).
  • Inside every Brand Folder is a random assortment of subfolders containing JSON files with various degrees of nesting inside different subfolders.

So a typical request would contain the following structure: Job Folder/Lang Folder/Brand Folder/...

And I want to transform all folders to follow this structure: Job Folder/Brand Folder/...

You can see an example below of how the folder structure currently looks and how I would like it to look in the end.

Structure of the folders and files before running the batch file:

  • French_Job1373
    • French
      • BrandA
        • Subfolder
          • Example.json
    • Manifest.xml
  • German_Job1374
    • German
      • BrandB
        • Subfolder1
          • Subfolder2
            • Subfolder3
              • ExampleFile.json
    • Manifest.xml
  • Japanese_Job1375
    • Japanese
      • BrandC
        • Subfolder1
          • Example.json
    • Manifest.xml
  • Korean_Job1376
    • Korean
      • BrandC
        • Subfolder1
          • Subfolder13
            • ExampleSrc.json
    • Manifest.xml

Structure of the folders and files as it should be after running the batch file:

  • French_Job1373
    • BrandA
      • Subfolder
        • Example.json
    • Manifest.xml
  • German_Job1374
    • BrandB
      • Subfolder1
        • Subfolder2
          • Subfolder3
            • ExampleFile.json
    • Manifest.xml
  • Japanese_Job1375
    • BrandC
      • Subfolder1
        • Example.json
    • Manifest.xml
  • Korean_Job1376
    • BrandC
      • Subfolder1
        • Subfolder13
          • ExampleSrc.json
    • Manifest.xml

I would like to have a batch file which essentially removes the Lang Folder, pulling everything from inside the Lang Folder one level up.

Following should be taken into consideration:

  • The file Manifest.xml should not be touched. It should remain inside the Job Folder level.
  • Everything from the Brand Folder level including the Brand Folder itself should be moved one level up (to the same level where the file Manifest.xml is).
  • The Language Folder (which at this point should be empty) should be deleted.
  • There is a finite list of possible languages after which the Lang Folder is named. If required to specify all possible languages in the batch file, I would like the option to add new languages to the list in the future.

So far, I have managed to get the batch file below to work as expected, but I need to run as many times as there are Job Folders and I have to place it inside the Language Folder to have it work as expected. If I place it anywhere else, it just deletes the Lang Folder with all of its contents and does not move anything. I am looking to have the batch file check all folders that are next to it and perform the operation as many times as needed.

What I have so far:

@echo off
if -%1==- echo No parameters! You must add %%P parameter! & pause & goto :EOF
cd /d %1
move * ..
for /d %%f in (*) do move %%f ..
cd ..
"%commander_path%\totalcmd.exe" /o /s %1\..
rd %1
FOR /d /r . %%d IN (Russian) DO @IF EXIST "%%d" rd /s /q "%%d"
FOR /d /r . %%d IN (French) DO @IF EXIST "%%d" rd /s /q "%%d"
FOR /d /r . %%d IN (German) DO @IF EXIST "%%d" rd /s /q "%%d"
FOR /d /r . %%d IN (Japanese) DO @IF EXIST "%%d" rd /s /q "%%d"
Mofi
  • 46,139
  • 17
  • 80
  • 143
Silver
  • 23
  • 2

1 Answers1

0

That is an excellent description of the folder moving task which can be done with a batch file stored in the folder containing all the Job Folders containing the following lines.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ErrorPause="
for /D %%I in ("%~dp0*_Job*") do for /F "eol=| delims=_" %%J in ("%%~nxI") do if exist "%%I\%%J\" (
    for /F "eol=| delims=" %%K in ('dir "%%I\%%J" /A /B 2^>nul') do move "%%I\%%J\%%K" "%%I\" 2>nul || (echo Failed to move:   "%%I\%%J\%%K"& set "ErrorPause=1")
    rd "%%I\%%J" 2>nul || (echo Failed to delete: "%%I\%%J"& set "ErrorPause=1")
)
if defined ErrorPause pause
endlocal

The first FOR loop searches in folder of the batch file referenced with %~dp0 (path ends always with a backslash) for non-hidden subfolders matching the wildcard pattern *_Job*. So assigned to loop variable I are one after the other the full qualified folder names of the Job Folders French_Job1373, German_Job1374, German_Job1374, Korean_Job1376, ...

The second FOR command splits up the current Job Folder name on underscores with everything up to first underscore assigned to loop variable J. That is the name of the Lang Folder in current Job Folder.

The IF condition checks if the Lang Folder in current Job Folder exists at all as otherwise there is nothing to do for the current Job Folder.

The third FOR loop starts one more command process in background with %ComSpec% /c and the command line within ' appended as additional arguments. So there is executed with Windows installed into C:\Windows and batch file path being C:\Temp, for example, for the first Lang Folder of first Job Folder:

C:\Windows\System32\cmd.exe /c dir "C:\Temp\French_Job1373\French" /A /B 2>nul

The command DIR outputs

  • all names of the folders and files including hidden ones because of option /A (all attributes)
  • in bare format because of option /B which means just folder/file name without path
  • in the specified directory.

FOR ignores folders and files with hidden attribute set which is the reason for using the DIR command line executed by a separate command process in the background.

Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.

FOR with option /F would split up by default all lines captured from handle STDOUT of background command process after started cmd.exe terminated itself into substrings using normal space and horizontal tab as string delimiters, would ignore next the line if the first substring starts with a semicolon being the default end of line character, and would otherwise assign just the first space/tab separated string to specified loop variable K. That behavior would be no problem according to the example for the folders BrandA, BrandB and two times BrandC. But the usage of the option string "eol=| delims=" results in using a vertical bar as end of line character which no folder/file name can contain and the definition of an empty list of string delimiters which disables line splitting behavior. So each folder/file name output by DIR without path is assigned completely to the loop variable K one after the other.

The command MOVE moves the current folder/file in Lang Folder of current Job Folder one level up into the Job Folder. This action is very fast as this is done by just updating the master file table of the file system which is cached by Windows. There is an error message output and the environment variable ErrorPause is defined if an error occurs on moving a folder or file up one level.

The current Lang Folder is removed with command RD after all folders and files in the current Lang Folder are moved up hopefully successfully. The deletion of the folder fails if a folder or file in Lang Folder could not be moved up because of a file in this folder tree is currently opened by an application, or a folder in this folder tree is the current folder of any running process, or a folder/file with same name exists already in Job Folder. An error message is output and the environment variable ErrorPause is defined on deletion of Lang Folder fails because of the folder is not empty.

The command PAUSE halts the batch file execution until a key is pressed if an error occurred. Otherwise the processing of the batch file ends without requiring any further user action.

The batch file can be simply executed once again in case of an error because of a file is opened in an application, or a folder is the current folder of a running process, or the folder/file to move exists already in Job Folder after closing the file in the application or the application itself respectively deletion of the folder/file in Job Folder.

To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

  • call /? ... explains %~dp0 ... drive and path of argument 0 which is the batch file path.
  • dir /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • move /?
  • pause /?
  • rd /?
  • set /?
  • setlocal /?

All these commands are internal commands of Windows command processor cmd.exe.

See also: Single line with multiple commands using Windows batch file

Mofi
  • 46,139
  • 17
  • 80
  • 143