DOS Batch file - Copy file based on filename into folder - batch-file

I would like to use a batch file to put them into default folder, but the account name is in the middle of the folder. Have any script I can use in dos command prompt?
888123AA.pdf
888123BB.pdf
888123CC.pdf
777456AA.pdf
777456BB.pdf
777456CC.pdf
Default folder:
999-888123-03
666-777456-01

#echo off
setlocal EnableDelayedExpansion
rem Process all .pdf files
for %%a in (*.pdf) do (
rem Get just the file name, ie: "888123AA"
set fileName=%%~Na
rem Using the file name minus two last chars, ie: "888123"
rem get the default folder with that name
for /D %%b in (*-!fileName:~0,-2!-*) do (
rem And copy the file to that folder
copy "%%a" "%%b"
)
)

I don't remember any apparent way to do it other than a UNIX shell... Maybe get MSYS and use that (outdated) bash to help?
Here is a bash script that can use after you installed bash from MSYS (or you can sort it with a Linux box - Ubuntu is no bigger than 800MB and can run as LiveCD without interfering your current Windows system, and the LiveCD can double as a system saver when needed. :-)
#!/bin/bash
for each in ./*; do
if [ -d $each ]; then # Only folders are minded.
# Extract the second part of the folder name.
ACCOUNT_NAME=`echo $each | sed "s/\\-/\n/" | head -n 2 | tail -n 1`
cp -v ./$ACCOUNT_NAME*.pdf $each
fi
done

Related

How to use rsync instead of move in for loop in batch

In every subfolder in the path U:\0012* I create an example folder and move the files from appropriate subfolder to example folder.
FOR /d %%A IN (U:\0012\*) DO mkdir %%~A\example & move %%~A\*.* %%~A\example\
What I want to try is to use rsync command instead of move
FOR /d %%A IN (U:\0012\*) DO
C:\cygwin\bin\rsync.exe -av -h --progress --checksum "/cygdrive/U/0012/%%A/*.*/" "/cygdrive/U/0012/%%A/EXAMPLE/"
The script is closing itself with a syntax error. Is it possible to use rsync in for loop?
I think you are having a clash of "Windows World" and "Unix World".
What you are trying with rsync, which is natural Unix tool, is to copy using a batch file path and put it into rsync path. This will not work.
I'll dissect your code:
In this part you are still in the "Windows world" you are using FOR to loop via the U:\0012\* path in a windows way FOR /d %%A IN (U:\0012\*) DO.
You have tried to "help" rsync with unix style path /cygdrive/U/0012/, but the variable %%A contains the windows style path!
C:\cygwin\bin\rsync.exe -av -h --progress --checksum "/cygdrive/U/0012/%%A/*.*/" "/cygdrive/U/0012/%%A/EXAMPLE/"
The error you are getting is probably something like:
The source and destination cannot both be remote. rsync error: syntax
or usage error (code 1) at main.c(1292) [Receiver=3.1.2]
How to solve such an error?
First is to say I'm using MSYS environment for linux tools. I have tested it on my local files.
In batch files you could do it the following way:
#echo off
FOR /d %%A IN (U:\0012\*) DO (
SET "copy_path=%%A"
C:\msys64\usr\bin\cygpath.exe -u %copy_path% > tmp_file.tmp
SET /P unix_path=<tmp_file.tmp
DEL tmp_file.tmp
ECHO "%unix_path%"
C:\msys64\usr\bin\rsync.exe -av -h --progress --checksum --remove-source-files "%unix_path%" "%unix_path%/EXAMPLE/"
)
)
The script takes the Window path C:\prg\PowerShell\test\SO\test1\* and then it uses a cygpath.exe to convert the path to a unix style path and saves it to temporary file (tmp_file.tmp). Then it reads from temporary file the path into the unix variable %unix_path% which is then used in the rsync.exe.
Note: As somebody already linked how to move file with rsync. I'll just state the option. You have to add --remove-source-files, which deletes files after transfer.
** Edit **
I think I now understand what you mean. Now rsync should really behave like move. Only difference is that if directory example exists it is copied with the file. (if it does not it is created and files moved there) - I think that was original intentions when looking at mkdir && move.
What I have done?
ENABLEDELAYEDEXPANSION to correctly read the variables from file (before it was only the last read)
"!unix_path!/" the last backslash is really important for rsync to behave correctly.
I have tested the script on my computer and for me it works as it should.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /D %%A IN (C:\prg\t\*) DO (
ECHO %%A
SET "copy_path=%%A"
C:\msys64\usr\bin\cygpath.exe -u !copy_path! > tmp_file.tmp
SET /P unix_path=<tmp_file.tmp
DEL tmp_file.tmp
ECHO "!unix_path!"
ECHO C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
)
** Second Edit ** Empty directories are not deleted with rsync
I do not recommend using --remove-files && --delete options during one operation due to the fact the rsync can fail. You can read more here superuser.com or unix stack exchange or even server fault.
I would simply go with already written solution: How to delete empty folders using windows command prompt? (I'm talking the solution (all credits to author) that takes in also directories with spaces):
for /f "usebackq delims=" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"
The final script would then look like this:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /D %%A IN (C:\prg\t\*) DO (
ECHO %%A
SET "copy_path=%%A"
C:\msys64\usr\bin\cygpath.exe -u !copy_path! > tmp_file.tmp
SET /P unix_path=<tmp_file.tmp
DEL tmp_file.tmp
ECHO "!unix_path!"
ECHO C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
C:\msys64\usr\bin\rsync.exe -av --progress --checksum --remove-source-files "!unix_path!/" "!unix_path!/example/"
)
REM To delete empty directories - the windows way
REM save current directory to stack
pushd
cd C:\prg\t
REM Will delete all empty directories (subdirectories) at current path
for /f "usebackq delims=" %%d in (`"dir /ad/b/s | sort /R"`) do rd "%%d"
REM return to saved directory
popd
rsync can run inside the for loop. Below is the sample code for moving all files from a directory to "EXAMPLE" directory in same directory.
#!/bin/sh
for d in ~/Desktop/a/*; do
rsync -rav -h --progress --checksum $d/*.* $d/EXAMPLE/
done
Save the above in a .sh file and run the file. Here the above code will go through all subdirectories in ~/Desktop/a/ directory and will create EXAMPLE directory in each subdirectory and copy all files to EXAMPLE directory.

Need to parse the current directory a batch file is in into a variable I can use in said batch file

Working with rsync on a windows machine (cWrsync) and I am syncing a large folder with sub directories to a web server which takes several minutes to complete. But when the user just needs to add a file to a sub-directory I don't want them to have to wait an hour to sync that directory.
My Idea
Add a file into each sub-directory (1_sync.bat) that they can execute when they add or delete a file within that directory. I need the batch file to be able to dynamically tell rsync which directory to sync.. here is the static version:
#echo off
REM Make environment variable changes local to this batch file
SETLOCAL
REM where ti find rsync and related files
SET CWRSYNCHOME=C:\cwRsync
SET HOME=C:\Users\greg\AppData\Roaming
SET CWORLDPATH=%PATH%
SET PATH=%CWRSYNCHOME%\BIN;%PATH%
"C:\cwRsync\bin\rsync.exe" -v -e 'ssh -i C:\home\greg\.ssh\id_rsa' --delete --recursive --inplace "/cygdrive/z/1CustomerDocs/2017/Client Folder/" "root#domainname.com:/var/storage/customer_files/2017/Client\ Folder/"
In the above example I would like to have Client Folder be a variable that will detect what folder the batch script is actually in so I can just through one of the bat files in every sub directory.
I tried %~dp0 which almost does the trick, but outputs the entire path.. I just need the last two directories.
so if %~dp0 = \SERVER-PATH\Content\1CustomerDocs\2017\Client Folder\
I wish I could cut the last two directories off and have a variable that looks like
2017/Client Folder (but also need one that escapes the spaces for linux)
So the end results would look like
#echo off
REM Make environment variable changes local to this batch file
SETLOCAL
REM where ti find rsync and related files
SET CWRSYNCHOME=C:\cwRsync
SET HOME=C:\Users\greg\AppData\Roaming
SET CWORLDPATH=%PATH%
SET PATH=%CWRSYNCHOME%\BIN;%PATH%
SET CUST_FOLDER_WINDOWS=*YOUR HELP NEEDED HERE*
SET CUST_FOLDER_LINUX=*YOUR HELP NEEDED HERE*
"C:\cwRsync\bin\rsync.exe" -v -e 'ssh -i C:\home\greg\.ssh\id_rsa' --delete --recursive --inplace "/cygdrive/z/1CustomerDocs/%CUST_FOLDER_WINDOWS%" "root#domainname.com:/var/storage/customer_files/%CUST_FOLDER_LINUX%"
And again, I would need the linux folder to escape spaces.
Thanks for the help!
To be independent from the current dirlevel:
#echo off
Echo current dir %CD%
Echo Batch dir %~dp0
for %%a in ("%~dp0.") Do Set "Parent=%%~nxa"
for %%a in ("%~dp0..") Do Set "Grandparent=%%~nxa"
Echo Last 2 dirs \%Grandparent%\%Parent%
current dir Q:\Test\2017\08\10
Batch dir Q:\Test\2017\08\10\
Last 2 dirs \08\10
Figured it how below
#echo off
REM Make environment variable changes local to this batch file
SETLOCAL
REM where ti find rsync and related files
SET CWRSYNCHOME=C:\cwRsync
SET HOME=C:\Users\greg\AppData\Roaming
SET CWORLDPATH=%PATH%
SET PATH=%CWRSYNCHOME%\BIN;%PATH%
for /F "tokens=5,6 delims=\" %%a in ("%0") do (
"C:\cwRsync\bin\rsync.exe" -v -e 'ssh -i C:\home\greg\.ssh\id_rsa' --delete --
recursive --inplace "/cygdrive/z/1CustomerDocs/%%a/%%b/"
"root#domainname.com:/var/storage/customer_files/%%a/%%b/"
)

Batch file check for anything in folder

I have been tinkering with some batch files to clean up some of my folders and I am stuck.
What I am trying to do is check the directory Installers for any files or folders and then either :goto empty or :goto notempty .
I have spent ages searching for a solution but everything that I have found is to either check if only files exist in a directory or check if a specified folder exists in a directory.
EDIT: This is what I have so far.
#echo off
echo Beginning File Cleanup
echo Installers Start
"C:\Program Files\WinRAR\rar.exe" a -r -df "Installers.rar" Installers
echo Installers Done
echo old Start
"C:\Program Files\WinRAR\rar.exe" a -r -df "old.rar" old
echo old Done
mkdir Installers
mkdir old
pause
The code above works but I only want it to run the rar.exe bit if the folder is empty hence to :goto requirement
Thanks
I must be missing something, but I didn't saw how does you current code relate to what you asked...
You can do what you want with the following line
dir /b "path/to/Installers" | findstr "^" >nul && (echo Folder not empty) || (echo Folder is empty)
Just see what happens at the echo parts and replace for the command you want.
Cheers.

Command Batch Script In Context Menu not working

I have a old batch script from nt/xp that runs from Context Menu. What it does is when I select a folder and run cmd it will create a temp folder in the active folder i right clicked in. Then will run a program to convert all the tiff's in the original folder and output the new images in the temp folder. New that I using windows 7, I'm having problems getting the CMD.exe to open in the working folder. when I use the script and right click it goes to /windows/system32 and not the folder I click on.
here are the reg file and batch to show what I want to do:
REG file:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Folder\shell\BW Comp/OV]
#="B&W Compress/OV"
[HKEY_CLASSES_ROOT\Folder\shell\BW Comp/OV\Command]
#="C:\\Program Files\\ISRU\\bin\\bwcov.cmd"
BATCH file:
mkdir temp
FOR %%j in (*.tif) do mr_file -T -S 128 -C j -Q 3 -K g %%~nj.tif temp\%%~nj.tif
This was a very simple setup but now with window 7 I can't get it to use the working folder in the batch when making DIR or processing images.
Try this batch file:
#echo off
pushd "%~1"
mkdir temp
FOR %%j in (*.tif) do mr_file -T -S 128 -C j -Q 3 -K g "%%~nj.tif" "temp\%%~nj.tif"
popd
if mr_file is a batch file also then it will need call before the name.
This batch file should work in the SENDTO menu also
but the registry file looks odd to me.
Foxidrive, I tried your suggestion and that work creating temp folder using folder I right clicked on.
Here are the new files.
Batch File (I used a new program called make_pry instead of mr_file:
#echo on
pushd "%~1"
Title %~f1
mkdir temp
FOR %%j in (*.tif) do make_pyr %%~nj.tif -TIFF -JPEG -QFACTOR 97 -tile 128 -out temp\%%~nj.tif
And Reg File (this file was also changed and was the only way I could get it to mkdir command to work in batch. If I remove the %1, /a or /c it will not work:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Folder\shell\BWCOV]
#="BW Compress OV"
[HKEY_CLASSES_ROOT\Folder\shell\BWCOV\command]
#="cmd.exe /a /c Inpho_bwcov.cmd %1"

How to create a loop/skip in batch

I am trying to download a chunk of files from an application. The shell command for it is 'go filename download'.
I have a text file containing all the filenames I have to download. All I want to do is to run a script/command such that when the above command is executed
1. the filenames are picked up from the textfile & executed using the above command
2. existing files/unavailable files are skipped
3. the process then continues with the next files in the list
So far I have this idea of using an operator like go $ download & then feed the operator with the text file containing the filenames list. Thanks in advance.
For Windows, you can use for /f to process the file and create a command from it. The following script supergo.cmd shows how this can be done:
#setlocal enableextensions enabledelayedexpansion
#echo off
for /f "delims=" %%f in (list.txt) do (
echo go "%%f" download
)
endlocal
The following transcripts shows it in operation:
C:\Pax> type list.txt
file1.txt
file number 2.txt
another file.jpg
C:\Pax> supergo
go "file1.txt" download
go "file number 2.txt" download
go "another file.jpg" download
If you're using a shell like bash, you can use sed to create a temporary script from the input file then run that:
#!/bin/bash
sed -e "s/^/echo go '/" -e "s/$/' download/" list.txt >/tmp/tempexec.$$
chmod u+x /tmp/tempexec.$$
. /tmp/tempexec.$$
rm -rf /tmp/tempexec.$$
This puts an echo go ' at the start of each line, a ' download at the end, then marks it executable and executes it.
In both cases (Windows and bash), remove the echo to get it to do the real work.

Resources