I am writing a dos script and I want to get the path of a file that is known so that the path can be used within the script to change to that directory to use the file specified and ouput log files to the same directory.
The script adds some directories to the path and changes to the required directory to execute a command using input files in the same directory. The command generates a number of files that are saved to the same directory.
Here is what i have so far
#ECHO OFF
:: Check argument count
set argC=0
for %%x in (%*) do Set /A argC+=1
IF %argC% LSS 3 (echo WARNING must include the parent Directory, the filename and the timestep for the simulation)
:: Assign meaningfull names to the input arguments
set parentDirectory=%1
set filename=%2
set scenarioTimestep=%3
:: Check validaty of the input arguments
:: TODO: implement check for directory, filename exists, and possibly limits to the timestep
IF "%parentDirectory%"=="" (
set parentDirectory=P:Parent\Directory
)
IF "%filename%"=="" (
set filename=ship2.xmf
)
IF "%scenarioTimestep%"=="" (
set scenarioTimestep=0.1
)
echo parent Directory: %parentDirectory%
echo filename: %filename%
echo timestep: %scenarioTimestep%
set MSTNFYURI=file:mst.log
set MSTNFYLEVEL=debug
set MSTNFYFLUSH=1
set XSFNFYURI=file:xsf.log
set XSFNFYLEVEL=debug
set XSFNFYFLUSH=1
set parentNFYURI=file:parent.log
set parentNFYLEVEL=debug
set parentNFYFLUSH=1
:: Add the parent directories to the path
set PATH=%parentDirectory%\bin\;%parentDirectory%\bin\ext\;%parentDirectory%\bin\gtkmm\;%parentDirectory%\bin\osg\;%PATH%
:: Change to the target directoy
set tagetDirectory=%parentDirectory%\examples\testing_inputs
cd %tagetDirectory%
echo command will be: ft -c %filename% -T %scenarioTimestep%
::ft -c %filename% -T %scenarioTimestep%
#ECHO ON
What i want to be able to do is instead of using the hard coded directory path examples\testing_inputs for targetDirectoy, i want to be able to search for the filename supplied and change directory to that path.
I know i can get the information displayed using
"dir filename.ext /s"
DOS ouptut
Volume in drive C is OS
Volume Serial Number is XXXX-XXXX
Directory of C:\Users\Me\parent\examples\testing_input
15/11/2012 02:51 PM <size> filename
...
...
How do i extract the directory form this info to be used within the script? Also if there is more than one file of the same name, how can i select the path based on the timestamp of the file?
for /f %%F in ('dir /B /S /A:-D filename.ext ') do set file_path=%%F
pushd %file_path%\..
dir_path=%CD%
popd
echo %file_path%
echo %dir_path%
is this what you looking for?
EDIT: Check dbenham's comment.
Related
We changed a DLL used by many windows programs.
I would like to create a script to replace all occurrences within all subfolders in various paths on our servers.
Below is a start on the script i need help with
setlocal enabledelayedexpansion
SET FromFile = "\\servernameFrom\folder\some.dll"
SET ToLocations = "\\servername1\sharename\" "\\servername2\sharename\" "\\servername2\sharename\"
for /l %%loc in (0,1,2) do (
echo Working on !ToLocations[%%loc]!
REM now do the recursive copy for that
for /r !ToLocations[%%loc]! %%f in (.) do (
copy FromFile "%%~ff" > nul
)
)
I want to use Mediainfo with a bat file.
It should write the Media Info into a textfile, then rename the file to *.nfo
That works quite good, but I always get the complete "standart" Media Info, not a custom one that I need.
Here is my code so far:
#echo off
set "mediainfo_path=C:\Program Files\mi cli\MediaInfo.exe"
set "output_extension=C:\Program Files\mi cli\custom.txt"
cd %1
echo.
echo Looking for Media Assets on target directory . . .
REM ******** Add media file extensions here ********
dir *.mkv /b /s > filelist.tmp
REM *
REM ******* Loop through temporary file list *******
(for /f "delims=" %%i in (filelist.tmp) do (
echo Extracting %%i metadata information . . .
setlocal enabledelayedexpansion
"!mediainfo_path!" --logfile="!output_extension" "%%i" > %%i.nfo
echo()
endlocal
)
del filelist.tmp
echo.
o matter what "output_extenstion" I choose, the result is always the same, full log.
First, you need to do step by step, so start by trying the MediaInfo command without the batch stuff. You'll see that it does not work.
"--logfile" is for storing the output (similar to your ">%%i.nfo") so you did not say to MediaInfo that you want a custom report.
mediainfo --Output=file://custom.txt a.mkv >a.nfo
or
mediainfo --Output=file://custom.txt a.mkv --LogFile=a.nfo
Would work as you expect (the first version both show and store info, the second version only store info).
So replace the "MediaInfo line" by:
"!mediainfo_path!" "--Output=file://!output_extension!" "%%i" > %%i.nfo
and it works as you expect.
Note: I am aware that there is a lack of documentation, due to lack of time :(.
Jérôme, developer of MediaInfo
My zip file has my folders inside. After unzipping my zip file, I want to iterate a loop for available folders inside the zip.
Inside loop condition is like below:
If my folder has index file (This is a file contains some data), then only I want to run some process (I know what this process is..). Otherwise we can ignore that folder.
Then loop will continue with other folder if there are anything
Thanks advance..
something like this?
(note: I assume $destdir will only contain the zipfile and its extraction!)
zipfile="/path/to/the/zipfile.zip"
destdir="/path/to/where/you/want/to/unzip"
indexfile="index.txt" #name of the index files
mkdir -p "$destdir" 2>/dev/null #make "sure" it exists.. but ignore errors in case it already exists
cd "$destdir" || { echo "Can not go into destdir=$destdir" ; Exit 1 ; }
#at that point, we are inside $destdir : we can start to work:
unzip "$zipfile"
for i in ./*/ ; do # you could change ./*/ to ./*/*/ if the zip contains a master directory too
cd "$i" && { #the && is important: you want to be sure you could enter that subdir!
if [ -e ./"$indexfile" ]; then
dosomething # you can define the function dosomething and use it here..
# or just place commands here
fi
cd - #we can safely this works, as we started there...
}
done
note: I iterate on ./*/ instead of */ as the dirname could contain a leding -, and therefore make cd -something not work (it would say it can't recognise some options!) ! this goes away with ./, cd ./-something will work !
I've created this very simple batch file for the sake of testing a concept I'm hoping to utilize. I need to recursively delete all of one type of file except in folders with a specific name. Here's my code:
:recur
FOR /f %%a IN ('DIR /b') DO (
IF EXIST %%a\NUL (
IF ["%%a" NEQ "subtest2"] (
ECHO %%a
CD %%a
CALL :recur
CD ..
)
)
COPY "*.cfm" "*_copy.cfm"
REM DEL "*_copy*.cfm"
)
Right now I'm just testing using copy instead of delete. Basically, this should create a copy of all the .cfm files except in the folder "subtest2". Right now it's recursively making the copies everywhere, including subtest2. How do I stop this?
The structure of my base directory is:
TestFolder
---subtest1
------test.pdf
------test.txt
------test.cfm
---subtest2
------test.pdf
------test.txt
------test.cfm
---test.pdf
---test.txt
---test.cfm
---recur.bat
The square brackets are not balanced on both sides of the IF comparison, so it can never match. The brackets are not part of the IF syntax. If present, they simply become part of the string that is compared. The same is true for any enclosing quotes. Remove the square brackets, and it will work (assuming there are no other problems)
Here is a simple method to accomplish your goal. I've prefixed the DEL command with ECHO for testing purposes:
for /r /d %%F in (*) do echo %%F\|findstr /liv "\\subtest2\\" >nul && echo del "%%F\*.cfm"
The FOR /R /D simply recurses all folders. The full path of each folder is piped into a FINDSTR command that looks for paths that do not contain a \subtest2 folder. The ECHO DEL command is only executed if the \subtest2\ folder is not found in the path.
Remove the last ECHO when you have confirmed the command gives the correct results.
Change %%F to %F if you want to run the command on the command line instead of in a batch file.
for f in `find . -path YOURDIR -prune -o print`
do
rm whateveryouwanttodelete
done
the find command in backticks finds all files but ignores the directory -prune you want to ignore. Then in the body of the loop you nuke the files. You can do even better with
find . -path YOURDIR -prune -o -print0 | xargs -0 rm -f
no need for the loop. DISCLAIMER: I haven't tested it so perhaps you want to start adopting it with cp instead of rm.
You can try this:
#echo off&setlocal
for /r /d %%i in (*) do (
pushd "%%i"
echo(%%i|findstr /ri "\\subtest2$" || COPY "*.cfm" "*_copy.cfm"
popd
)
I have a highly structured hierarchical directory containing multiple files that need to be moved into a flat structure and renamed at the same time. The original path and name must be logged along with the new path and name and eventually loaded into a database. Finally, each renamed file must get a unique, unguessable (IE: encrypted or hashed) file name. When the renamed file is moved into the new directory structure, I also want to limit the # of files in each directory, so each directory would be created with a sequential number for its name and then the files would be loaded into it until a maximum number of files was reached (eg: 255) before rolling into a new directory with the next sequential number for its name.
Is there a tool / software that does this? I did some initial research and nothing came up with the following criteria:
batch rename & copy into alternative (flatter) structure
hash / encrypt filename and ensure uniqueness
sequentially name folders and limit file count
log each file's original name and path, and new (encrypted) name and path
I have several Bash scripts I have used in the past to migrate hand-made file repositories to hashed repositories to be accessed and managed from a web application (mostly PHP apps). In these repositories filenames are hashed (to avoid collisions with files with the same content/name) and files are distributed evenly (in a deterministic fashion or randomly) to keep files-per-dir count low for performance reasons. The following is one fully-working example:
#!/bin/bash
MAXFILESPERDIR=500
TARGETROOTDIR="./newrepository"
RANDOMDISTRIBUTION=1
if [ -d "$1" ]; then
LOGFILE=$(basename $0).$(date +"_%Y%m%d_%H%M").${$}.log
SQLFILE=$(basename $0).$(date +"_%Y%m%d_%H%M").${$}.sql
SOURCEDIR="$1"
TOTALSOURCEFILES=$(find "$1" -type f | wc -l)
let "TOTALTARGETDIRS=$TOTALSOURCEFILES / $MAXFILESPERDIR"
PADLENTARGETDIRS=${#TOTALTARGETDIRS}
PADLENTARGETFILE=${#TOTALSOURCEFILES}
echo "We will create $TOTALTARGETDIRS directories to hold $MAXFILESPERDIR files per directory."
if [ "$RANDOMDISTRIBUTION" == "1" ] ; then
echo "We will rename and distribute each file randomly."
else
echo "We will rename and distribute each file uniformly."
fi
echo "Do you want to continue?"
select choice in yes no ; do
if [ "$choice" == "yes" ] ; then
COUNTER=1
find "$1" -type f | while read SOURCEFILE ; do {
CHECKSUMFILE=$(sha1sum "$SOURCEFILE" | cut -d " " -f 1)
CHECKSUMNAME=$(echo "$SOURCEFILE" | sha1sum | cut -d " " -f 1)
DETERMINISTICNONCE=$(printf "%0${PADLENTARGETFILE}d\n" $COUNTER)
if [ "$RANDOMDISTRIBUTION" == "1" ] ; then
PROBABILISTICNONCE=$(let "XX=$RANDOM % $TOTALTARGETDIRS + 1" ; printf "%0${PADLENTARGETDIRS}d\n" $XX;)
else
PROBABILISTICNONCE=$(let "XX=$COUNTER % $TOTALTARGETDIRS + 1" ; printf "%0${PADLENTARGETDIRS}d\n" $XX;)
fi
FILEDATE=$(stat -c %z "$SOURCEFILE" | cut -d "." -f 1)
FILESIZE=$(stat -c %s "$SOURCEFILE")
echo "Source file $SOURCEFILE" >> $LOGFILE
echo "Target file $TARGETROOTDIR/$PROBABILISTICNONCE/$PROBABILISTICNONCE$CHECKSUMFILE$DETERMINISTICNONCE" >> $LOGFILE
echo "INSERT INTO files (Filename, Location, Checksum, CDate, Size) VALUES ('$PROBABILISTICNONCE$CHECKSUMFILE$DETERMINISTICNONCE', '$PROBABILISTICNONCE', '$CHECKSUMFILE', '$FILEDATE', $FILESIZE);" >> $SQLFILE
mkdir -p $TARGETROOTDIR/$PROBABILISTICNONCE
cp -v "$SOURCEFILE" $TARGETROOTDIR/$PROBABILISTICNONCE/$PROBABILISTICNONCE$CHECKSUMFILE$DETERMINISTICNONCE
let "COUNTER+=1"
} ; done
echo "Done."
echo
break
fi
if [ "$choice" == "no" ] ; then
echo
echo "Operation cancelled"
echo
break
fi
done
else
echo
echo "Missing source directory"
echo
fi
Just run it from the root of your new repository. You can configure it modifying the first variables: MAXFILESPERDIR defines how many files to store per-directory, TARGETROOTDIR is the name of the first-level directory to create the first level directory (it uses only two levels, the first one is really a single root), and RANDOMDISTRIBUTION defines if the files will be distributed randomly (it may look uneven, specially for small runs) or deterministically (just counting).
How it works (FYI, just in case this is not what you are looking for but maybe you can get some ideas):
Count the source files.
Calculate how many target directories will create.
Ask for confirmation.
For each file:
Calculate the SHA1 hash for the file content.
Create a deterministic nonce.
Create a probabilistic nonce (if RANDOMDISTRIBUTION is 1, otherwise just a counter).
Get the size and modification date.
Combine the values of the random value with the hash and the counter to get the new file name (the path will be the random value).
Log the source and target full paths.
Create and log a SQL insert query.
Create the target directory (if it does not exist).
Copy the file. (You can move it if you want but I'm playing safe).
Finish
If you set RANDOMDISTRIBUTION to 1 and run the script several times, you'll get duplicates of your source files, as each file will get different target filename/path each time you run it. If RANDOMDISTRIBUTION is set to something else, everytime you run the script the files will be renamed the same way (for the same file set, if you add or remove files, they will get different names/paths).
The objective of using a random value + hash + counter is to be sure we can handle duplicates (won't collide thanks to the counter) while still distributing the files randomly (for long enough runs, this will distribute the files evenly).
Also, the preffix of the generated file name is the name of the directory too, so that if you have the file name and the directory name length, you can calculate the directory name (just in case you don't store that in your database table).
Finally, this is a one-time migration script, it was not really written to be executed regularly over the same set of files.