0

I am trying to write a bat script in order to better organize my clients' files. I have created two folders. The first one is named "folders" and contains the folders for each client with their files. Every client's folder name has the the structure name_surname_uniqueclientid. The second one is named "Raw" and contains raw client files and folders but each folder or file contains inside its name the unique client id. My goal is to extract every id from each "folders" folder and check if there are any files or folders inside the "Raw" folder that contain this id. If there are it should xcopy them inside the corresponding "folders" folder with the same id.
My problem is i cannot check for folders that contain the id and move them to the corresponding "folders" folder.

I have managed to extract the id from the folder's name, check for files inside "Raw" folder containing this id and xcopy them to the corresponding "folders" folder. As far as i can tell the script doesn't enter the last if. It should find the folders containing the id and if there are xcopy them to the corresponding "folders" folder.

    @echo off

    setlocal enabledelayedexpansion
    for /d %%a in ("folders\*") do (
        for /f "tokens=3 delims=_" %%t in ("%%~nxa") do ( 
        if exist "Raw\*%%t*" (
            xcopy "Raw\*%%t*" "%%a"
            )

This part bellow doesn't work:

        if exist Raw\*%%t*\ (
            xcopy "Raw\*%%t*\*" "%%a" /s /i
            echo ok
            )
        )
    )
    pause   
    goto :eof

Initial Folder Tree

C:\DATA
├───folders
│   ├───FirstName_Lastname_10123
│   │   |
│   │   │   kjhda10123.rtf
│   │   │   dadsada10123lhlhfds.txt
│   │   │
│   │   └───kjhfdsfs10123f
│   ├───FirstName_Lastname_10124
│   │   │   jgkjgjfs10124kjlda.rtf
│   │   │   klhlidkas10124klhdas.txt
│   │   │
│   │   └───lkhjlkhdsakda10124
│   └───FirstName_Lastname_10125
│       │   kjhkdsa10125.rtf
│       │   10125dakjh.txt
│       │
│       └───10125
|           |   kjhkjda.txt
|           |   hkda.pdf  
└───Raw
    |   dsakhkhda10123.txt
    |   kgjddjasg10125.pdf
    |   kkkkdajh10123khda.docx
    |   10124dsadas
    |   
    └───vcb10125

After

C:\DATA
├───folders
│   ├───FirstName_Lastname_10123
│   │   |   kkkkdajh10123khda.docx
│   │   │   kjhda10123.rtf
│   │   │   dadsada10123lhlhfds.txt
|   |   |   dsakhkhda10123.txt
│   │   │
│   │   └───kjhfdsfs10123f
│   ├───FirstName_Lastname_10124
│   │   │   jgkjgjfs10124kjlda.rtf
│   │   │   klhlidkas10124klhdas.txt
│   │   │   10124dsadas
│   │   └───lkhjlkhdsakda10124
│   └───FirstName_Lastname_10125
│       │   kjhkdsa10125.rtf
│       │   10125dakjh.txt
│       │   kgjddjasg10125.pdf
|       |   vcb10125
│       └───10125
|           |   kjhkjda.txt
|           |   hkda.pdf  
└───Raw
    |   
    |   
    |   
    |   
    |   
    └───

If a folder already exists merge

Kjssplass
  • 33
  • 7

2 Answers2

1

Question? (I know this will get downvoted but I want to help the OP and try and clearly understand the issue)

  1. So, trying to make this clear, you have two main directories called folders & Raw correct?

  2. Inside the folders contains each clients folder named in your name_surname_uniqueclientid format correct?

  3. Inside Raw you have "raw client files and folders" BUT each with the name format of name_surname_uniqueclientid correct?

  4. Guessing the actuall name of the folder is after the _uniqueclientid in example _10123_taxing.rtf ...?

Folder Tree?

C:\DATA
├───folders
│   ├───FirstName_Lastname_10123
│   ├───FirstName_Lastname_10124
│   └───FirstName_Lastname_10125
└───Raw
    │   FirstName_Lastname_10123_taxing.rtf
    │   FirstName_Lastname_10123_text.txt
    │   FirstName_Lastname_10124_data.rtf
    │   FirstName_Lastname_10124_text.txt
    │   FirstName_Lastname_10125.rtf
    │   FirstName_Lastname_10125_text.txt
    │
    ├───FirstName_Lastname_10123_taxing
    ├───FirstName_Lastname_10124_numbers
    └───FirstName_Lastname_10125_names

Goal?

So if any files inside the Raw folder contain uniqueclientid in the name you want to copy them to the name_surname_uniqueclientid contained inside the folders ..?

New Tree ?

C:\DATA
├───folders
│   ├───FirstName_Lastname_10123
│   │   │   FirstName_Lastname_10123_taxing.rtf
│   │   │   FirstName_Lastname_10123_text.txt
│   │   │
│   │   └───FirstName_Lastname_10123_taxing
│   ├───FirstName_Lastname_10124
│   │   │   FirstName_Lastname_10124_data.rtf
│   │   │   FirstName_Lastname_10124_text.txt
│   │   │
│   │   └───FirstName_Lastname_10124_numbers
│   └───FirstName_Lastname_10125
│       │   FirstName_Lastname_10125.rtf
│       │   FirstName_Lastname_10125_text.txt
│       │
│       └───FirstName_Lastname_10125_names
└───Raw

EDIT: (Working Solution)

If this indeed was your question, then this is a working solution to your problem. Keep note that all functions, code blocks, and processes have a Rem | that explains it step by step in the code.

So using the bases of your code, we can grab the uniqueclientid and from there we will be setting this as a string called FolderIDNumber. This string will be used inside a find to only display valid folders inside the dir loops.

With the main folders name_surname_uniqueclientid folder being used in a loop, we are free to process the files in Raw to move over. This is easy as we now have all the data for dir. The reason we have two dir loops is so one only grabs Folders and the other only grabs Files. This way we can properly COPY them to the designated name_surname_uniqueclientid folder.

@echo off
@setlocal enabledelayedexpansion

Rem | Configure Directories
Set "FolderLocation=C:\DATA\folders"
Set "RawLocation=C:\DATA\Raw"

Rem | Get All Folders Locations In X Directory
for /d %%A in ("!FolderLocation!\*") do (

    Rem | Set Raw Location
    Set "FoldersLoc=%%A"

    Rem | Get Each ID# From %%A
    for /f "tokens=3 delims=_" %%B in ("%%A") do (

        Rem | Set Folders ID#
        Set "FolderIDNumber=%%B"

    )

    Rem | Get Each Folder W/H !FolderIDNumber!
    for /f "tokens=*" %%C in ('Dir "!RawLocation!\" /B /A:D^| find "!FolderIDNumber!"') do (

        Rem | Set Raw Location & Name
        Set "RawFolderLoc=!RawLocation!\%%C"
        Set "RawFoldersName=%%~nC"

        Rem | Move Folders
        robocopy "!RawFolderLoc!" "!FoldersLoc!\!RawFoldersName!" /E /NJH /NJS /NDL /NFL /NC /NS>NUL

    )

    Rem | Get Each File W/H !FolderIDNumber!
    for /f "tokens=*" %%D in ('Dir "!RawLocation!\*.*" /B /A-D^| find "!FolderIDNumber!"') do (

        Rem | Set Raw Location
        Set "RawFileLoc=!RawLocation!\%%D"

        Rem | Move Files
        copy "!RawFileLoc!" "!FoldersLoc!">NUL

    )

)
goto :EOF

For help on any of the commands do the following:

  • call /?
  • set /?
  • for /?
  • if /?
  • find /?
  • So on.
John Kens
  • 1,615
  • 2
  • 10
  • 28
  • Solution added to text. – John Kens Jan 10 '19 at 06:21
  • @Kjssplass, I think to add to John's help section. Open cmd.exe, type `help` and press enter, where you will be provided with a complete list of commands available in cmd. simply select them and run `nameofcmd /?` to see help on what they do. – Gerhard Jan 10 '19 at 06:26
  • I should have made a folder tree from the beginning. It would have been more helpful. 1.That is correct. 2.That is correct. 3.That is not correct. The files inside "Raw" folder contain the unique_client_id randomly inside their name. For example: dkahdksa10123dlkhda.txt The folders too. 4.That is not 100% correct. There are folders inside the "Raw" folder that their name is only the unique_client_id but not all of them. – Kjssplass Jan 10 '19 at 06:36
  • 1
    @Kjssplass how about editing your post and adding some sample input and expected output data? – Gerhard Jan 10 '19 at 06:45
  • @Kjssplass My Script already does that? You are taking files from raw and moving them into there correct `folders` with the persons `ID` Folder. – John Kens Jan 10 '19 at 17:39
  • 1
    The only difference between your edited response and my response was that my script put these files/folders from raw and moved them to there correct folders with the persons ID Folder but created a ` \Raw\ ` folder to put them in. I have edited my tree's and script to not create the raw folder. Try the script and let me know the result. – John Kens Jan 10 '19 at 17:47
  • There is a small problem. When it finds a folder inside "Raw" that its name contains an unique id when it copies it it renames it as the client folder. For example from my folder tree: 10124dsadas folder will be copied inside FirstName_Lastname_10124 folder and renamed to FirstName_Lastname_10124. I want it to keep the original name (10124dsadas) and if there is a folder inside already named after (10124dsadas) ask what to do. – Kjssplass Jan 11 '19 at 00:23
  • @Kjssplass Yeah I see your problem. Looks like a small code mistake. Fixing now, will update you when I finish. – John Kens Jan 11 '19 at 00:36
  • 1
    @Kjssplass Script was tweaked try it now. PS: `robocopy` has an `/IS` & `/IT` switch. The `/IS` = `copy if attributes are equal` I suggest you use the `/IT` so `copy if attributes differ`. You can also combine these switches to `copy irrespective of attributes`. Hope this fixes your problem. – John Kens Jan 11 '19 at 00:57
  • @Kjssplass Happy to help! – John Kens Jan 11 '19 at 01:42
  • @JohnKens When copying the files or folders it overwrites if there is a file/folder with the same name. Can you modify your answer in order to keep both files/folders? And if it doesn't find a file or folder it says file not found. Can we add an if exists to find command? – Kjssplass Jan 31 '19 at 18:51
  • @Kjssplass Before you move or copy the files. You can use an `if exists` command to check if they already exists. Take a look at this response. https://stackoverflow.com/a/5251790/8667430 - By adding a counter you can simply rename the duplicate file with a number. You will want to have a foor loop to extract the _# at the end and set that as the first `set count=` string so it will add up from your latest file/folder. At the end of the `( )` code block put and `) ELSE (` then you can put the copy/move script as it was not found. – John Kens Jan 31 '19 at 22:50
  • Some of my files contain carets and it doesn't copy them. I know it should be a better solution to rename them, but except the fact that they are too many, they are exported from a specific software that reads them as they are. Is there any way we can overcame this? – Kjssplass Mar 05 '19 at 19:17
1

IMO your approach isn't that bad,
but instead of an if you need another for to iterate/parse the files/folders found in RAW.

I'd also move the files, not copy:

:: Q:\Test\2019\01\10\SO_54120642.cmd
@echo off
Set "Base=C:\Data\folders"
Set "Src=C:\Data\Raw"

for /d %%A in ("%Base%\*") do (
    for /f "tokens=3 delims=_" %%T in ("%%~nxA") do (
        for /f "delims=" %%F in ('dir /B /A "%Src%\*%%T*" 2^>Nul') Do ( 
            Move "%Src%\%%F" "%%A\"
        )
    )
)
pause   
goto :eof

With your tree emulated on my ramdrive this ended up:

> tree /F
└───DATA
    ├───folders
    │   ├───FirstName_Lastname_10123
    │   │   │   dadsada10123lhlhfds.txt
    │   │   │   dsakhkhda10123.txt
    │   │   │   kjhda10123.rtf
    │   │   │   kkkkdajh10123khda.docx
    │   │   │
    │   │   └───kjhfdsfs10123f
    │   ├───FirstName_Lastname_10124
    │   │   │   10124dsadas
    │   │   │   jgkjgjfs10124kjlda.rtf
    │   │   │   klhlidkas10124klhdas.txt
    │   │   │
    │   │   └───lkhjlkhdsakda10124
    │   └───FirstName_Lastname_10125
    │       │   10125dakjh.txt
    │       │   hkda.pdf
    │       │   kgjddjasg10125.pdf
    │       │   kjhkdsa10125.rtf
    │       │   kjhkjda.txt
    │       │
    │       ├───10125
    │       └───vcb10125
    └───Raw