Batch move files based on part of file name - Windows 8 - batch-file

I've got a number of files I'm trying to sort through for my PhD research. I'm not familiar with using Batch files but I do have some coding experience.
I'm trying to move the files based on part of their filename into folders generated automatically for them in the directory they're currently in.
The files were generated as part of a series of pXRF analyses on brass objects held at a museum.
Some examples of the file structure:
01-64.1007-1-LID.pdz
01-64.1007-2-BASE.pdz
02-67.1765-1.pdz
02-67.1765-2.pdz
02-67.1765-3.pdz
etc.
Basically the file structure works like this:
The first number is my unique identifier for the object, then a hyphen, then the museums unique identifier, then a hyphen, then a number to show which analysis of the object. Finally, there may or may not be a small descriptor (i.e. BASE or LID) which helps me identify where I performed the scan.
So to break it down 01-64.1007-1-LID means Object 1 - Museum Accession Number 64.1007 - First Analysis - Performed on the lid of the object - .pdz is the file extension.
02-67.1765-2 means Object 2 - Museum Accession Number 67.1765 - Second Analysis etc.
What I want to do is move:
01-64.1007-1-LID.pdz
01-64.1007-2-BASE.pdz
into a folder called:
01-64.1007
and
02-67.1765-1.pdz
02-67.1765-2.pdz
02-67.1765-3.pdz
into a folder called:
02-67.1765
etc.
I've seen a few scripts which may help with this but I'm unsure how to tweak them for my purposes. If anyone can help I'd really appreciate it!
Thanks,
Mike

Test this batch file in a folder of sample files: call it movepdz.bat so the name doesn't clash with another executable.
#echo off
for %%a in (*.pdz) do (
echo processing "%%a"
for /f "tokens=1,2 delims=-" %%b in ("%%~nxa") do (
md "%%b-%%c" 2>nul
move "%%a" "%%b-%%c" >nul
)
)
pause

If you really mean a bash script, you can use something like this:
for file in *.pdz; do
dir=${echo "$file"|cut -d- -f -2}
mkdir -p "$dir"
mv "$file" "$dir"
done
The cut command will cut out the part before the second hyphen to determine the directory name. Then we create the directory in case it is not already present. Finally simply move the file in that directory.
Update: Thanks for clarifying your environment. (I was sure the question mentioned bash before...) - If you want to use this solution you could install git which comes with a nice git-bash.

Related

Deciphering "Make EXE from BAT" Script written by Jason Faulker

I came across a way to convert my .bat with dependencies on tool to an .exe file. However when I try using the script and run the .exe created, I always getting an error. Seems I modified the script incorrectly.
Anyone can help, please?
Here's the code with my modifications:
#ECHO OFF
ECHO Make EXE From BAT
ECHO Written by: Jason Faulkner
ECHO SysadminGeek.com
ECHO.
ECHO.
REM Usage:
MakeExeFromBat BatFileToConvert -bat MyProgram.bat
REM
REM Required Parameters:
BatFileToConvert -save MyProgram
REM Source batch file to use to produce the output Exe file.
REM
REM Optional Parameters:
IncludeFile -include Tool.exe
REM Additional files to include in the Exe file.
REM You can include external tools used by the batch file so they are available on the executing machine.
SETLOCAL
REM Configuration (no quotes needed):
SET PathTo7Zip=C:\Desktop\
REM ---- Do not modify anything below this line ----
SET OutputFile="%~n1.exe"
SET SourceFiles="%TEMP%\MakeEXE_files.txt"
SET Config="%TEMP%\MakeEXE_config.txt"
SET Source7ZFile="%Temp%\MakeEXE.7z"
REM Remove existing files
IF EXIST %OutputFile% DEL %OutputFile%
REM Build source archive
ECHO "%~dpnx1" > %SourceFiles%
:AddInclude
IF {%2}=={} GOTO EndInclude
ECHO "%~dpnx2" >> %SourceFiles%
SHIFT /2
GOTO AddInclude
:EndInclude
"%PathTo7Zip%\7za.exe" a %Source7ZFile% #%SourceFiles%
REM Build config file
ECHO ;!#Install#!UTF-8! > %Config%
ECHO RunProgram="%~nx1" >> %Config%
ECHO ;!#InstallEnd#! >> %Config%
REM Build EXE
COPY /B "%PathTo7Zip%\7zsd.sfx" + %Config% + %Source7ZFile% %OutputFile%
REM Clean up
IF EXIST %SourceFiles% DEL %SourceFiles%
IF EXIST %Config% DEL %Config%
IF EXIST %Source7ZFile% DEL %Source7ZFile%
ENDLOCAL
This doesn't really convert a bat file to an exe. It just creates a selfextracting archive (exe) which contains the bat file. On execution it extracts the file to a temporary folder and runs it from there. You can even extract the bat from the exe just by using 7zip/rar/winzip or any other archiver.
If you want to convert a bat to an exe for real you should use one of the tools from the web (like this one: http://www.f2ko.de/index.php?lang=en) or concider using a simple script language like AutoIt.
If you pick the second, you can simply execute your bat code with Run("put your bat code in here") and you can compile your script to a "real" exe file.
For an alternative approach, you can basically do the same thing as described in the accepted answer (making a 7z-SFX) with WinRAR. That way, you can also do it with a GUI, and I will try to add some more useful information.
Actually, you can also use the latter approach to generate portable applications and it also works with "converting" every runnable (or openable) file into an .exe.
If you need that "portability hack", you should unpack your .exe or .msi installer with Universal Extractor. Details can be found in this Article, Step 1 to 4. Newer Versions of 7zip or WinRAR also come with comparable features.
Now you add all needed files to the archive. In the easiest case, this is just your .bat script or whatever file you want to "convert" into an .exe applivation. (Step 5 here)
Steps 6 and 7 are just some Settings for the SFX-Archive, 8 is the interesting one, as you select what you actually want to run there. Input the name of your (.bat-)file.
Step 9 lets you select where to unpack to - you do this setting manually and programmatically in the MakeExeFromBat.bat-script.
After this process you created a Portable App in SFX archiever form, enjoy
The word "converting" was put into quotation marks, because running that .exe actually works like this:
The contents of the (SFX-)EXE file are extracted from the "archive part" to a directory as the specified temp directory.
( The config file generated by the script is read. )
The file, that was previously contained in the EXE file and then extracted, is now executed in a new window.
a) This file could besides a .bat be anything - as e.g. an image, a MP3 or a video
b) or also a Python Script (of course your OS needs to know how to deal with that file.
Once finished, the temp files are removed.
You can also derive some limitations from that. If you have a .bat that needs the content of the working directory, you will have a problem. (Say, a batch that renames all files in the current dir from 1 to n.) In some cases that can be dealt with by adding all needed files to the archive too. On Windows Vista and all newer OSes, you might encounter a message box after the script is run. After selecting ‘This program installed correctly’, the message box will not be displayed in the future for this file. Because the EXE file launches in a new window, the typical way of logging output (using the > char) will not work as expected. In order to log the output, you would need to handle this natively in your source script.
All references were already linked, but once again: Big credit goes to Jason Faulkner for providing the Article and 7zip-Approach, binbert for the WinRAR-SFX Solution (which is as hinted much more versatile -> portability) and some credit to creative8 for finding the two and the article comparing them.
Actually, I was develping another solution using AutoHotkey. In my case, I just want to be able to add my .bat to the windows start menu - but the options are not limited to that.
The script itself is just a oneliner and .AHK is easily converted to .exe (I used v1.1.33.09):
run % SubStr(A_ScriptName, 1, -4) ;// run also has the option to run your file minimized or hidden, see the source 2 below
Source 2
What it does is taking its own name, removing the .ahk or .exe respectively (the last 4 characters, hence -4) and running excactly that. Usage could not be easier: you have a runme.bat, so you rename the program I provide to runme.bat.exe. Say you want the .exe to open an image.png - guess what, rename it to image.png.exe. You get the gist - that's it. It dynamically checks its name to find what to run. In my opinion, this is not much less mighty than "unpacking the .bat and then run it", but (again imho) it is much more elegant.
Use it as you wish, I should probably start a public github page or so.

SVN Update specific files from repository only

There's this repository which is many many gigabytes, 99% of which I don't need. What I want to do is get/update only the *.js *.css *.html .doc and *.pdf files. The rest, which are the enormous ones, I want to leave up there and not waste time and disk space getting because I don't need to look at them and I'll never be changing them.
I realize that the svn:ignore feature isn't what I need, that's related only to what gets checked in and what gets ignored. I also know that there's no parameters or settings in SVN that I can take advantage of to do what I want.
What I have found though is that if I right-click on my SVN folder and select "Check for Modifications" and then in the next dialog choose "Check repository" then I get a full list of the files I don't have. It's then an easy task to add "Extension" to the column headers and sort by extension. I can then scroll down and find all the .js files grouped together.
Here's where my #fail happens. If I right-click on ONE of the JS files and select UPDATE, then it will bring the file down and create the sub-directory hierarchy necessary to support that file. This is exactly what I'd want to happen. At this point I jump in the air thinking I've found what I need. This isn't such a troublesome process, I can live with this. Then I selected all of the JS files and right-clicked. First thing I noticed is that the context menu that appears has less options, that's troubling. But the UPDATE option is there, so I'm not too worried. I choose UPDATE then click OK, just like I did for the one single JS file I'd earlier tried. What happens next is the weird thing though. Instead of repeating the process that happened with the one single file, but this time to all selected files, it shows "Skipped" against each file and reports it's done. This happens every time. I can do each file manually (which would take hours) but I can't do them all at once.
Help. I'm doing this in a virtual machine which I'd rather not quadruple the size of just to get files I don't need.
Sorry for the delayed answer, there's been a lot going on and I also had to spend some time to get this working. As you already noted, there is no straightforward way to do an "extension-only-checkout". But there is a way using Subversion command-line tools and a batch script I wrote. It works by using the sparse directories feature of Subversion, which lets you specify which "depth" a checkout should have. By specifying a depth of empty, an empty working copy is created and no files or folders are actually checked out. Then, you can update immediate files and folders of your choice from the repository into that working copy. This allows to create that "extension-only-checkout" which you're after.
The script I wrote allows you to specify multiple extensions in the EXTENSIONS variable separated by spaces. The repository specified in the SVN_ROOT variable is then scanned for files with the given extensions. Then it proceeds to build up a working copy which consists only of the directory structure needed to support the files having the extensions you specified (using the method described above). I tested it quite a bit and hope it will suit your needs.
Note: Depending on the size of the repository and the number of files matching the specified extensions, the process of creating the working copy will take some time.
#ECHO OFF
SetLocal EnableDelayedExpansion
SET SVN_ROOT=svn://your-repository.com/svn/your-project
SET EXTENSIONS=.js .css .html .doc .pdf
SET ROOT_DIR=%CD%
ECHO Listing repository...
svn -R ls %SVN_ROOT% > _files-all.txt
REM filter list for specified extensions
FOR %%H IN (%EXTENSIONS%) DO (
TYPE _files-all.txt | FINDSTR /I /R "%%H$" >> _files-selected.txt
)
REM initial checkout in empty mode
svn co %SVN_ROOT% --depth empty .
FOR /F "tokens=*" %%I IN (_files-selected.txt) DO (
REM "escape" path elements by wrapping them into double quotes
SET TMP_PATH=%%I
SET TMP_PATH="!TMP_PATH:/=" "!"
ECHO Fetching %%I
REM iterate over path elements
FOR %%J IN (!TMP_PATH!) DO (
REM "unescape" each path element again
SET PATH_ELEM=%%J
SET PATH_ELEM=!PATH_ELEM:~1,-1!
REM if we don't have this element, fetch it from repository
IF NOT EXIST "!PATH_ELEM!" (
svn up %%J --depth empty 2>&1 > nul
)
REM if the element is a directory, enter it
IF EXIST %%~sJ\NUL CD %%J
)
CD !ROOT_DIR!
)
REM clean up temporary files
DEL _files-all.txt _files-selected.txt
I ended up having to abandon my dreams of having an svn update that only gets me certain file extensions and leaves all others on the server. I had to accept I need to get the whole thing, unless I want each update to involve navigating a large tree structure and selecting only the sub-folders I want.

Batch incrementation from external file

I have a script who creates new tags in a SVN, and add some files. I want to automate this task so I would like to find some way to do automatically the incrementation for the tags name, from 1.0 to X.0.
I thought about a conf file who would contains "1.0" as a first version number and who would be overwrite at each call to the script. But not sure I can get the "1.0" value from the file and then do an incrementation on it in my script.
Any help would be really appreciate.
Thanks in advance
Don't create a seed configuration file. Instead, let the batch script default to 1.0 if file does not exist.
#echo off
setlocal
set "conf=version.conf"
if not exist "%conf%" (set version=1.0) else (
for /f "usebackq delims=." %%N in ("%conf%") do set /a version=%%N+1
)
set "version=%version%.0"
(echo %version%)>"%conf%"
I'm assuming you will never run this process multiple times in parallel - it can fail if you do run in parallel. Modifications can be made to lock the conf file so you can run in parallel if need be. See the accepted answer to how to check in command line if given file or directory is locked, that it is used by a process? for more info.
Take a look at keywords in Subversion using autoprops.
First, setup subversion to honor keyword expansion
enable-auto-props = yes
[auto-props]
version.txt = svn:keywords=Revision
Then, setup a simple file, let's call it version.txt with the $revision$ keyword and some random content.
$revision$
Random content
Then, in your batch file, recreate the version.txt file with new random content
echo $revision$ >version.txt
echo %random% %date% %time% >>version.txt
and check in this new file every time your batch file is run, so it will become
$revision 32 $
4214 Mon 21/01/2013 15:53:27,62
This way, subversion will keep an accurate version number of all the runs of the batch file, even in multiple clients and simultaneosly.
You might then extract and use the revision number from version.txt with code similar to
for /f "tokens=1,2" %%a in (version.txt) do (
if %%a==$revision (
echo Revision number is %%b
echo do something with %%b, create %%b tag or whatever
)
)
Since you don't say what language you want to use only general remarks can be given:
It certainly is possible to maintain a small 'version' file holding the 'dottet version number', something like 0.2.6 maybe. That files content can be read by any process. You should implement a little collection of methods to split that content into its numerical tokens (major and minor version and the like). Those numerical values can be processed by any mathematical function you like to use. For example you can increment them. Another method would be some 'implode' function that takes the numerical tokens and creates again a 'dottet version number' (now maybe 0.2.7...) and finally you can write that information back into the file. It certainly makes sense to allow an argument that controls which part of the version should be incremented.
Such scheme is not really efficient, but often sufficient.
Note, that such approach will only work if you can guarantee that it is always only a single process to access that version file. Otherwise multiple processes might overwrite each others results which certainly is a cause of problems.
As an alternative, maybe a more elegant alternative, you might consider treating the subversion repository itself as seed storage for your version number: instead of reading a special files content (what if that file is deleted or something else happens?) make a request to the tags folder inside subversion. It should contain all previously tagged versions. So that is precisely the information you want. Take all version numbers, sort them, take the highest one and process it as above.

.bat file to rename and move files with prompt

I am completely new to this, but I am trying to create a .bat file that will allow me to rename a pair of files within a designated folder and move them into a subfolder. The part I am having trouble with is that I am wanting a prompt to come up to identify/select the files to be renamed and moved.
Example file names are:
A1234, A1235, A1236, B1234, B1235, B1236, etc.
Is there a way to bring up a prompt that allows the user to type the shared name (ex 1234)of the files and rename and move both files to the designated subfolder?
Any and all help would be appreciated!
Suggested approach
for part of problem
part I am having trouble with is that I am wanting a prompt to come
up to identify/select the files to be renamed and moved. Is there a
way to bring up a prompt that allows the user to type the shared name
(ex 1234)of the files and rename and move both files to the designated
subfolder?
Do a search operation using wildcard, like "?1234" for the case highlighted above ( should be made generalized for all acceptable and expected patterns "*1234*" is the generic most )
Now do a RENAME inside a For loop on the results obtained by search.
As you suggest you are a newbie with Batch, following tutorials will help you build your file. Look for elements like Variables, For Loop
Batch Tutorial
Here you go
#echo off
set /p file=Please type shared name:
for %%a in (C:\Folder\?%file%.*) do (
move "%%a" subdir
ren "subdir\%%a" newname.*
)

DOS command to move all files in subdirectories one level up without overwriting same file name, unique size

MY QUESTION:
I have the same situation as Rishi. I have a number of versions of the same song by the same artist that appear on different CD's. If I use the batch command as written, will DOS overwrite songs with the same name, even if the file size is different for each unique file?
PREVIOUS QUESTION: DOS command to move all files in subdirectories one level up
REFERENCE Rishi asked the question on Jan 15th:
"I have a folder with a lot of sub folders with one or more files in each. I am trying to write a batch file that moves all those files to C:\songs (for example).
C:>FOR /R C:\Test %i IN (*) DO MOVE %i C:\Songs
The folders Test and songs exist, but I get an error saying
%i was unexpected at this time.
What am I doing wrong?"
ANSWER WAS
"FOR /R %i IN (C:\Test*) DO MOVE "%i" C:\Songs
In a batch file, it has to be %%i. Weird quirk of batch."
Within a given folder there can only be one version of a file with a given name. When executed within a batch, the MOVE command will automatically overwrite any pre-existing file of the same name. So the answer to your question is - YES, a file with the same name will be over-written, even if it has a different file size. (Note - if you are using Windows XP then you are not using DOS)
You can prevent a batch move from overwriting an existing file by piping N to MOVE with the -y option:
echo n | move /-y "%%~i" "C:\songs\"
If you want to copy and preserve both versions into the same folder, then at least one version will have to be renamed. You will have to decide what kind of naming scheme you want to use before you can begin coming up with a solution.

Resources